You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

issues_controller_test.rb 235KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997
  1. # frozen_string_literal: true
  2. # Redmine - project management software
  3. # Copyright (C) 2006-2020 Jean-Philippe Lang
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. require File.expand_path('../../test_helper', __FILE__)
  19. class IssuesControllerTest < Redmine::ControllerTest
  20. fixtures :projects,
  21. :users, :email_addresses, :user_preferences,
  22. :roles,
  23. :members,
  24. :member_roles,
  25. :issues,
  26. :issue_statuses,
  27. :issue_relations,
  28. :versions,
  29. :trackers,
  30. :projects_trackers,
  31. :issue_categories,
  32. :enabled_modules,
  33. :enumerations,
  34. :attachments,
  35. :workflows,
  36. :custom_fields,
  37. :custom_values,
  38. :custom_fields_projects,
  39. :custom_fields_trackers,
  40. :time_entries,
  41. :journals,
  42. :journal_details,
  43. :queries,
  44. :repositories,
  45. :changesets,
  46. :watchers, :groups_users
  47. include Redmine::I18n
  48. def setup
  49. User.current = nil
  50. end
  51. def test_index
  52. with_settings :default_language => "en" do
  53. get :index
  54. assert_response :success
  55. # links to visible issues
  56. assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  57. assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
  58. # private projects hidden
  59. assert_select 'a[href="/issues/6"]', 0
  60. assert_select 'a[href="/issues/4"]', 0
  61. # project column
  62. assert_select 'th', :text => /Project/
  63. end
  64. end
  65. def test_index_should_not_list_issues_when_module_disabled
  66. EnabledModule.where("name = 'issue_tracking' AND project_id = 1").delete_all
  67. get :index
  68. assert_response :success
  69. assert_select 'a[href="/issues/1"]', 0
  70. assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
  71. end
  72. def test_index_should_list_visible_issues_only
  73. get(:index, :params => {:per_page => 100})
  74. assert_response :success
  75. Issue.open.each do |issue|
  76. assert_select "tr#issue-#{issue.id}", issue.visible? ? 1 : 0
  77. end
  78. end
  79. def test_index_with_project
  80. with_settings :display_subprojects_issues => '0' do
  81. get(:index, :params => {:project_id => 1})
  82. assert_response :success
  83. # query form
  84. assert_select 'form#query_form' do
  85. assert_select 'div#query_form_with_buttons.hide-when-print' do
  86. assert_select 'div#query_form_content' do
  87. assert_select 'fieldset#filters.collapsible'
  88. assert_select 'fieldset#options'
  89. end
  90. assert_select 'p.buttons'
  91. end
  92. end
  93. assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  94. assert_select 'a[href="/issues/5"]', 0
  95. end
  96. end
  97. def test_index_with_project_and_subprojects
  98. with_settings :display_subprojects_issues => '1' do
  99. get(:index, :params => {:project_id => 1})
  100. assert_response :success
  101. assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  102. assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
  103. assert_select 'a[href="/issues/6"]', 0
  104. end
  105. end
  106. def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
  107. @request.session[:user_id] = 2
  108. with_settings :display_subprojects_issues => '1' do
  109. get(:index, :params => {:project_id => 1})
  110. assert_response :success
  111. assert_select 'a[href="/issues/1"]', :text => /Cannot print recipes/
  112. assert_select 'a[href="/issues/5"]', :text => /Subproject issue/
  113. assert_select 'a[href="/issues/6"]', :text => /Issue of a private subproject/
  114. end
  115. end
  116. def test_index_with_project_and_default_filter
  117. get(
  118. :index,
  119. :params => {
  120. :project_id => 1,
  121. :set_filter => 1
  122. }
  123. )
  124. assert_response :success
  125. # default filter
  126. assert_query_filters [['status_id', 'o', '']]
  127. end
  128. def test_index_with_project_and_filter
  129. get(
  130. :index,
  131. :params => {
  132. :project_id => 1,
  133. :set_filter => 1,
  134. :f => ['tracker_id'],
  135. :op => {
  136. 'tracker_id' => '='
  137. },
  138. :v => {
  139. 'tracker_id' => ['1']
  140. }
  141. }
  142. )
  143. assert_response :success
  144. assert_query_filters [['tracker_id', '=', '1']]
  145. end
  146. def test_index_with_short_filters
  147. to_test = {
  148. 'status_id' => {
  149. 'o' => {:op => 'o', :values => ['']},
  150. 'c' => {:op => 'c', :values => ['']},
  151. '7' => {:op => '=', :values => ['7']},
  152. '7|3|4' => {:op => '=', :values => ['7', '3', '4']},
  153. '=7' => {:op => '=', :values => ['7']},
  154. '!3' => {:op => '!', :values => ['3']},
  155. '!7|3|4' => {:op => '!', :values => ['7', '3', '4']}
  156. },
  157. 'subject' => {
  158. 'This is a subject' => {:op => '=', :values => ['This is a subject']},
  159. 'o' => {:op => '=', :values => ['o']},
  160. '~This is part of a subject' => {:op => '~', :values => ['This is part of a subject']},
  161. '!~This is part of a subject' => {:op => '!~', :values => ['This is part of a subject']}
  162. },
  163. 'tracker_id' => {
  164. '3' => {:op => '=', :values => ['3']},
  165. '=3' => {:op => '=', :values => ['3']}
  166. },
  167. 'start_date' => {
  168. '2011-10-12' => {:op => '=', :values => ['2011-10-12']},
  169. '=2011-10-12' => {:op => '=', :values => ['2011-10-12']},
  170. '>=2011-10-12' => {:op => '>=', :values => ['2011-10-12']},
  171. '<=2011-10-12' => {:op => '<=', :values => ['2011-10-12']},
  172. '><2011-10-01|2011-10-30' => {:op => '><', :values => ['2011-10-01', '2011-10-30']},
  173. '<t+2' => {:op => '<t+', :values => ['2']},
  174. '>t+2' => {:op => '>t+', :values => ['2']},
  175. 't+2' => {:op => 't+', :values => ['2']},
  176. 't' => {:op => 't', :values => ['']},
  177. 'w' => {:op => 'w', :values => ['']},
  178. '>t-2' => {:op => '>t-', :values => ['2']},
  179. '<t-2' => {:op => '<t-', :values => ['2']},
  180. 't-2' => {:op => 't-', :values => ['2']}
  181. },
  182. 'created_on' => {
  183. '>=2011-10-12' => {:op => '>=', :values => ['2011-10-12']},
  184. '<t-2' => {:op => '<t-', :values => ['2']},
  185. '>t-2' => {:op => '>t-', :values => ['2']},
  186. 't-2' => {:op => 't-', :values => ['2']}
  187. },
  188. 'cf_1' => {
  189. 'c' => {:op => '=', :values => ['c']},
  190. '!c' => {:op => '!', :values => ['c']},
  191. '!*' => {:op => '!*', :values => ['']},
  192. '*' => {:op => '*', :values => ['']}
  193. },
  194. 'estimated_hours' => {
  195. '=13.4' => {:op => '=', :values => ['13.4']},
  196. '>=45' => {:op => '>=', :values => ['45']},
  197. '<=125' => {:op => '<=', :values => ['125']},
  198. '><10.5|20.5' => {:op => '><', :values => ['10.5', '20.5']},
  199. '!*' => {:op => '!*', :values => ['']},
  200. '*' => {:op => '*', :values => ['']}
  201. }
  202. }
  203. default_filter = {'status_id' => {:operator => 'o', :values => ['']}}
  204. to_test.each do |field, expression_and_expected|
  205. expression_and_expected.each do |filter_expression, expected|
  206. get(:index, :params => {:set_filter => 1, field => filter_expression})
  207. assert_response :success
  208. expected_with_default =
  209. default_filter.
  210. merge({field => {:operator => expected[:op], :values => expected[:values]}})
  211. assert_query_filters(
  212. expected_with_default.map {|f, v| [f, v[:operator], v[:values]]}
  213. )
  214. end
  215. end
  216. end
  217. def test_index_with_project_and_empty_filters
  218. get(
  219. :index,
  220. :params => {
  221. :project_id => 1,
  222. :set_filter => 1,
  223. :fields => ['']
  224. }
  225. )
  226. assert_response :success
  227. # no filter
  228. assert_query_filters []
  229. end
  230. def test_index_with_project_custom_field_filter
  231. field =
  232. ProjectCustomField.
  233. create!(:name => 'Client', :is_filter => true, :field_format => 'string')
  234. CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
  235. CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
  236. filter_name = "project.cf_#{field.id}"
  237. @request.session[:user_id] = 1
  238. get(
  239. :index,
  240. :params => {
  241. :set_filter => 1,
  242. :f => [filter_name],
  243. :op => {
  244. filter_name => '='
  245. },
  246. :v => {
  247. filter_name => ['Foo']
  248. },
  249. :c => ['project']
  250. }
  251. )
  252. assert_response :success
  253. assert_equal [3, 5], issues_in_list.map(&:project_id).uniq.sort
  254. end
  255. def test_index_with_project_status_filter
  256. project = Project.find(2)
  257. project.close
  258. project.save
  259. get(
  260. :index,
  261. :params => {
  262. :set_filter => 1,
  263. :f => ['project.status'],
  264. :op => {'project.status' => '='},
  265. :v => {'project.status' => ['1']}
  266. }
  267. )
  268. assert_response :success
  269. issues = issues_in_list.map(&:id).uniq.sort
  270. assert_include 1, issues
  271. assert_not_include 4, issues
  272. end
  273. def test_index_with_query
  274. get(
  275. :index,
  276. :params => {
  277. :project_id => 1,
  278. :query_id => 5
  279. }
  280. )
  281. assert_response :success
  282. assert_select '#sidebar .queries' do
  283. # assert only query is selected in sidebar
  284. assert_select 'a.query.selected', 1
  285. # assert link properties
  286. assert_select(
  287. 'a.query.selected[href=?]',
  288. '/projects/ecookbook/issues?query_id=5',
  289. :text => "Open issues by priority and tracker"
  290. )
  291. # assert only one clear link exists
  292. assert_select 'a.icon-clear-query', 1
  293. # assert clear link properties
  294. assert_select(
  295. 'a.icon-clear-query[title=?][href=?]',
  296. 'Clear',
  297. '/projects/ecookbook/issues?set_filter=1&sort=',
  298. 1
  299. )
  300. end
  301. end
  302. def test_index_with_query_grouped_by_tracker
  303. get(
  304. :index,
  305. :params => {
  306. :project_id => 1,
  307. :query_id => 6
  308. }
  309. )
  310. assert_response :success
  311. assert_select 'tr.group span.count'
  312. end
  313. def test_index_with_query_grouped_and_sorted_by_category
  314. get(
  315. :index,
  316. :params => {
  317. :project_id => 1,
  318. :set_filter => 1,
  319. :group_by => "category",
  320. :sort => "category"
  321. }
  322. )
  323. assert_response :success
  324. assert_select 'tr.group span.count'
  325. end
  326. def test_index_with_query_grouped_and_sorted_by_fixed_version
  327. get(
  328. :index,
  329. :params => {
  330. :project_id => 1,
  331. :set_filter => 1,
  332. :group_by => "fixed_version",
  333. :sort => "fixed_version"
  334. }
  335. )
  336. assert_response :success
  337. assert_select 'tr.group span.count'
  338. end
  339. def test_index_with_query_grouped_and_sorted_by_fixed_version_in_reverse_order
  340. get(
  341. :index,
  342. :params => {
  343. :project_id => 1,
  344. :set_filter => 1,
  345. :group_by => "fixed_version",
  346. :sort => "fixed_version:desc"
  347. }
  348. )
  349. assert_response :success
  350. assert_select 'tr.group span.count'
  351. end
  352. def test_index_grouped_by_due_date
  353. set_tmp_attachments_directory
  354. Issue.destroy_all
  355. Issue.generate!(:due_date => '2018-08-10')
  356. Issue.generate!(:due_date => '2018-08-10')
  357. Issue.generate!
  358. get(
  359. :index,
  360. :params => {
  361. :set_filter => 1,
  362. :group_by => "due_date"
  363. }
  364. )
  365. assert_response :success
  366. assert_select 'tr.group span.name', :value => '2018-08-10' do
  367. assert_select '~ span.count', :value => '2'
  368. end
  369. assert_select 'tr.group span.name', :value => '(blank)' do
  370. assert_select '~ span.count', :value => '1'
  371. end
  372. end
  373. def test_index_grouped_by_created_on_if_time_zone_is_utc
  374. # TODO: test fails with mysql
  375. skip if mysql?
  376. skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on}
  377. @request.session[:user_id] = 2
  378. User.find(2).pref.update(time_zone: 'UTC')
  379. get(
  380. :index,
  381. :params => {
  382. :set_filter => 1,
  383. :group_by => 'created_on'
  384. }
  385. )
  386. assert_response :success
  387. assert_select 'tr.group span.name', :text => '07/19/2006' do
  388. assert_select '+ span.count', :text => '2'
  389. end
  390. end
  391. def test_index_grouped_by_created_on_if_time_zone_is_nil
  392. skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on}
  393. current_user = User.find(2)
  394. @request.session[:user_id] = current_user.id
  395. current_user.pref.update(time_zone: nil)
  396. get(
  397. :index,
  398. :params => {
  399. :set_filter => 1,
  400. :group_by => 'created_on'
  401. }
  402. )
  403. assert_response :success
  404. # group_name depends on localtime
  405. group_name = format_date(Issue.second.created_on.localtime)
  406. assert_select 'tr.group span.name', :text => group_name do
  407. assert_select '+ span.count', :text => '2'
  408. end
  409. end
  410. def test_index_grouped_by_created_on_as_pdf
  411. skip unless IssueQuery.new.groupable_columns.detect {|c| c.name == :created_on}
  412. get(
  413. :index,
  414. :params => {
  415. :set_filter => 1,
  416. :group_by => 'created_on',
  417. :format => 'pdf'
  418. }
  419. )
  420. assert_response :success
  421. assert_equal 'application/pdf', response.media_type
  422. end
  423. def test_index_with_query_grouped_by_list_custom_field
  424. get(
  425. :index,
  426. :params => {
  427. :project_id => 1,
  428. :query_id => 9
  429. }
  430. )
  431. assert_response :success
  432. assert_select 'tr.group span.count'
  433. end
  434. def test_index_with_query_grouped_by_key_value_custom_field
  435. cf = IssueCustomField.
  436. create!(
  437. :name => 'Key',
  438. :is_for_all => true,
  439. :tracker_ids => [1, 2, 3],
  440. :field_format => 'enumeration'
  441. )
  442. cf.enumerations << valueb = CustomFieldEnumeration.new(:name => 'Value B', :position => 1)
  443. cf.enumerations << valuea = CustomFieldEnumeration.new(:name => 'Value A', :position => 2)
  444. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => valueb.id)
  445. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => valueb.id)
  446. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => valuea.id)
  447. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  448. get(
  449. :index,
  450. :params => {
  451. :project_id => 1,
  452. :set_filter => 1,
  453. :group_by => "cf_#{cf.id}"
  454. }
  455. )
  456. assert_response :success
  457. assert_select 'tr.group', 3
  458. assert_select 'tr.group' do
  459. assert_select 'span.name', :text => 'Value B'
  460. assert_select 'span.count', :text => '2'
  461. end
  462. assert_select 'tr.group' do
  463. assert_select 'span.name', :text => 'Value A'
  464. assert_select 'span.count', :text => '1'
  465. end
  466. end
  467. def test_index_with_query_grouped_by_user_custom_field
  468. cf = IssueCustomField.
  469. create!(
  470. :name => 'User',
  471. :is_for_all => true,
  472. :tracker_ids => [1, 2, 3],
  473. :field_format => 'user'
  474. )
  475. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  476. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  477. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  478. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  479. get(
  480. :index,
  481. :params => {
  482. :project_id => 1,
  483. :set_filter => 1,
  484. :group_by => "cf_#{cf.id}"
  485. }
  486. )
  487. assert_response :success
  488. assert_select 'tr.group', 3
  489. assert_select 'tr.group' do
  490. assert_select 'a', :text => 'John Smith'
  491. assert_select 'span.count', :text => '1'
  492. end
  493. assert_select 'tr.group' do
  494. assert_select 'a', :text => 'Dave Lopper'
  495. assert_select 'span.count', :text => '2'
  496. end
  497. end
  498. def test_index_grouped_by_boolean_custom_field_should_distinguish_blank_and_false_values
  499. cf = IssueCustomField.
  500. create!(
  501. :name => 'Bool',
  502. :is_for_all => true,
  503. :tracker_ids => [1, 2, 3],
  504. :field_format => 'bool'
  505. )
  506. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '1')
  507. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
  508. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '')
  509. with_settings :default_language => 'en' do
  510. get(
  511. :index,
  512. :params => {
  513. :project_id => 1,
  514. :set_filter => 1,
  515. :group_by => "cf_#{cf.id}"
  516. }
  517. )
  518. assert_response :success
  519. end
  520. assert_select 'tr.group', 3
  521. assert_select 'tr.group', :text => /Yes/
  522. assert_select 'tr.group', :text => /No/
  523. assert_select 'tr.group', :text => /blank/
  524. end
  525. def test_index_grouped_by_boolean_custom_field_with_false_group_in_first_position_should_show_the_group
  526. cf = IssueCustomField.
  527. create!(
  528. :name => 'Bool',
  529. :is_for_all => true,
  530. :tracker_ids => [1, 2, 3],
  531. :field_format => 'bool',
  532. :is_filter => true
  533. )
  534. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '0')
  535. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '0')
  536. with_settings :default_language => 'en' do
  537. get(
  538. :index,
  539. :params => {
  540. :project_id => 1,
  541. :set_filter => 1, "cf_#{cf.id}" => "*",
  542. :group_by => "cf_#{cf.id}"
  543. }
  544. )
  545. assert_response :success
  546. end
  547. assert_equal [1, 2], issues_in_list.map(&:id).sort
  548. assert_select 'tr.group', 1
  549. assert_select 'tr.group', :text => /No/
  550. end
  551. def test_index_with_query_grouped_by_tracker_in_normal_order
  552. 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
  553. get(
  554. :index,
  555. :params => {
  556. :set_filter => 1,
  557. :group_by => 'tracker',
  558. :sort => 'id:desc'
  559. }
  560. )
  561. assert_response :success
  562. assert_equal ["Bug", "Feature request", "Support request"],
  563. css_select("tr.issue td.tracker").map(&:text).uniq
  564. end
  565. def test_index_with_query_grouped_by_tracker_in_reverse_order
  566. 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
  567. get(
  568. :index,
  569. :params => {
  570. :set_filter => 1,
  571. :group_by => 'tracker',
  572. :c => ['tracker', 'subject'],
  573. :sort => 'id:desc,tracker:desc'
  574. }
  575. )
  576. assert_response :success
  577. assert_equal ["Bug", "Feature request", "Support request"].reverse,
  578. css_select("tr.issue td.tracker").map(&:text).uniq
  579. end
  580. def test_index_with_query_id_and_project_id_should_set_session_query
  581. get(
  582. :index,
  583. :params => {
  584. :project_id => 1,
  585. :query_id => 4
  586. }
  587. )
  588. assert_response :success
  589. assert_kind_of Hash, session[:issue_query]
  590. assert_equal 4, session[:issue_query][:id]
  591. assert_equal 1, session[:issue_query][:project_id]
  592. end
  593. def test_index_with_invalid_query_id_should_respond_404
  594. get(
  595. :index,
  596. :params => {
  597. :project_id => 1,
  598. :query_id => 999
  599. }
  600. )
  601. assert_response 404
  602. end
  603. def test_index_with_cross_project_query_in_session_should_show_project_issues
  604. q = IssueQuery.
  605. create!(
  606. :name => "cross_project_query", :user_id => 2,
  607. :project => nil, :column_names => ['project']
  608. )
  609. @request.session[:issue_query] = {:id => q.id, :project_id => 1}
  610. with_settings :display_subprojects_issues => '0' do
  611. get(:index, :params => {:project_id => 1})
  612. end
  613. assert_response :success
  614. assert_select 'h2', :text => q.name
  615. assert_equal ["eCookbook"], css_select("tr.issue td.project").map(&:text).uniq
  616. end
  617. def test_private_query_should_not_be_available_to_other_users
  618. q = IssueQuery.
  619. create!(
  620. :name => "private", :user => User.find(2),
  621. :visibility => IssueQuery::VISIBILITY_PRIVATE,
  622. :project => nil
  623. )
  624. @request.session[:user_id] = 3
  625. get(:index, :params => {:query_id => q.id})
  626. assert_response 403
  627. end
  628. def test_private_query_should_be_available_to_its_user
  629. q = IssueQuery.
  630. create!(
  631. :name => "private", :user => User.find(2),
  632. :visibility => IssueQuery::VISIBILITY_PRIVATE,
  633. :project => nil
  634. )
  635. @request.session[:user_id] = 2
  636. get(:index, :params => {:query_id => q.id})
  637. assert_response :success
  638. end
  639. def test_public_query_should_be_available_to_other_users
  640. q = IssueQuery.
  641. create!(
  642. :name => "public", :user => User.find(2),
  643. :visibility => IssueQuery::VISIBILITY_PUBLIC,
  644. :project => nil
  645. )
  646. @request.session[:user_id] = 3
  647. get(:index, :params => {:query_id => q.id})
  648. assert_response :success
  649. end
  650. def test_index_should_omit_page_param_in_export_links
  651. get(:index, :params => {:page => 2})
  652. assert_response :success
  653. assert_select 'a.atom[href="/issues.atom"]'
  654. assert_select 'a.csv[href="/issues.csv"]'
  655. assert_select 'a.pdf[href="/issues.pdf"]'
  656. assert_select 'form#csv-export-form[action="/issues.csv"]'
  657. end
  658. def test_index_should_not_warn_when_not_exceeding_export_limit
  659. with_settings :issues_export_limit => 200 do
  660. get :index
  661. assert_select '#csv-export-options p.icon-warning', 0
  662. end
  663. end
  664. def test_index_should_warn_when_exceeding_export_limit
  665. with_settings :issues_export_limit => 2 do
  666. get :index
  667. assert_select '#csv-export-options p.icon-warning', :text => %r{limit: 2}
  668. end
  669. end
  670. def test_index_should_include_query_params_as_hidden_fields_in_csv_export_form
  671. get(
  672. :index,
  673. :params => {
  674. :project_id => 1,
  675. :set_filter => "1",
  676. :tracker_id => "2",
  677. :sort => 'status',
  678. :c => ["status", "priority"]
  679. }
  680. )
  681. assert_select '#csv-export-form[action=?]', '/projects/ecookbook/issues.csv'
  682. assert_select '#csv-export-form[method=?]', 'get'
  683. assert_select '#csv-export-form' do
  684. assert_select 'input[name=?][value=?]', 'set_filter', '1'
  685. assert_select 'input[name=?][value=?]', 'f[]', 'tracker_id'
  686. assert_select 'input[name=?][value=?]', 'op[tracker_id]', '='
  687. assert_select 'input[name=?][value=?]', 'v[tracker_id][]', '2'
  688. assert_select 'input[name=?][value=?]', 'c[]', 'status'
  689. assert_select 'input[name=?][value=?]', 'c[]', 'priority'
  690. assert_select 'input[name=?][value=?]', 'sort', 'status'
  691. end
  692. get(
  693. :index,
  694. :params => {
  695. :project_id => 1,
  696. :set_filter => "1",
  697. :f => ['']
  698. }
  699. )
  700. assert_select '#csv-export-form input[name=?][value=?]', 'f[]', ''
  701. end
  702. def test_index_should_show_block_columns_in_csv_export_form
  703. field = IssueCustomField.
  704. create!(
  705. :name => 'Long text', :field_format => 'text',
  706. :full_width_layout => '1',
  707. :tracker_ids => [1], :is_for_all => true
  708. )
  709. get :index
  710. assert_response :success
  711. assert_select '#csv-export-form' do
  712. assert_select 'input[value=?]', 'description'
  713. assert_select 'input[value=?]', 'last_notes'
  714. assert_select 'input[value=?]', "cf_#{field.id}"
  715. end
  716. end
  717. def test_index_csv
  718. get(:index, :params => {:format => 'csv'})
  719. assert_response :success
  720. assert_equal 'text/csv', @response.media_type
  721. assert response.body.starts_with?("#,")
  722. lines = response.body.chomp.split("\n")
  723. # default columns + id and project
  724. assert_equal Setting.issue_list_default_columns.size + 2, lines[0].split(',').size
  725. end
  726. def test_index_csv_with_project
  727. get(
  728. :index,
  729. :params => {
  730. :project_id => 1,
  731. :format => 'csv'
  732. }
  733. )
  734. assert_response :success
  735. assert_equal 'text/csv', @response.media_type
  736. end
  737. def test_index_csv_without_any_filters
  738. @request.session[:user_id] = 1
  739. Issue.
  740. create!(
  741. :project_id => 1, :tracker_id => 1,
  742. :status_id => 5, :subject => 'Closed issue', :author_id => 1
  743. )
  744. get(
  745. :index,
  746. :params => {
  747. :set_filter => 1,
  748. :f => [''],
  749. :format => 'csv'
  750. }
  751. )
  752. assert_response :success
  753. # -1 for headers
  754. assert_equal Issue.count, response.body.chomp.split("\n").size - 1
  755. end
  756. def test_index_csv_with_description
  757. Issue.generate!(:description => 'test_index_csv_with_description')
  758. with_settings :default_language => 'en' do
  759. get(
  760. :index,
  761. :params => {
  762. :format => 'csv',
  763. :c => [:tracker, :description]
  764. }
  765. )
  766. assert_response :success
  767. end
  768. assert_equal 'text/csv', response.media_type
  769. headers = response.body.chomp.split("\n").first.split(',')
  770. assert_include 'Description', headers
  771. assert_include 'test_index_csv_with_description', response.body
  772. end
  773. def test_index_csv_with_spent_time_column
  774. issue = Issue.
  775. create!(
  776. :project_id => 1, :tracker_id => 1,
  777. :subject => 'test_index_csv_with_spent_time_column',
  778. :author_id => 2
  779. )
  780. TimeEntry.
  781. create!(
  782. :project => issue.project, :issue => issue,
  783. :hours => 7.33, :user => User.find(2),
  784. :spent_on => Date.today
  785. )
  786. get(
  787. :index,
  788. :params => {
  789. :format => 'csv',
  790. :set_filter => '1',
  791. :c => %w(subject spent_hours)
  792. }
  793. )
  794. assert_response :success
  795. assert_equal 'text/csv', @response.media_type
  796. lines = @response.body.chomp.split("\n")
  797. assert_include "#{issue.id},#{issue.subject},7.33", lines
  798. end
  799. def test_index_csv_with_all_columns
  800. get(
  801. :index,
  802. :params => {
  803. :format => 'csv',
  804. :c => ['all_inline']
  805. }
  806. )
  807. assert_response :success
  808. assert_equal 'text/csv', @response.media_type
  809. assert_match /\A#,/, response.body
  810. lines = response.body.chomp.split("\n")
  811. assert_equal IssueQuery.new.available_inline_columns.size, lines[0].split(',').size
  812. end
  813. def test_index_csv_with_multi_column_field
  814. CustomField.find(1).update_attribute :multiple, true
  815. issue = Issue.find(1)
  816. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  817. issue.save!
  818. get(
  819. :index,
  820. :params => {
  821. :format => 'csv',
  822. :c => ['tracker', "cf_1"]
  823. }
  824. )
  825. assert_response :success
  826. lines = @response.body.chomp.split("\n")
  827. assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
  828. end
  829. def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
  830. field =
  831. IssueCustomField.
  832. create!(
  833. :name => 'Float',
  834. :is_for_all => true,
  835. :tracker_ids => [1],
  836. :field_format => 'float'
  837. )
  838. issue =
  839. Issue.
  840. generate!(
  841. :project_id => 1, :tracker_id => 1,
  842. :custom_field_values => {field.id => '185.6'}
  843. )
  844. with_settings :default_language => 'fr' do
  845. get(
  846. :index,
  847. :params => {
  848. :format => 'csv',
  849. :c => ['id', 'tracker', "cf_#{field.id}"]
  850. }
  851. )
  852. assert_response :success
  853. issue_line =
  854. response.body.chomp.split("\n").
  855. map {|line| line.split(';')}.
  856. detect {|line| line[0]==issue.id.to_s}
  857. assert_include '185,60', issue_line
  858. end
  859. with_settings :default_language => 'en' do
  860. get(
  861. :index,
  862. :params => {
  863. :format => 'csv',
  864. :c => ['id', 'tracker', "cf_#{field.id}"]
  865. }
  866. )
  867. assert_response :success
  868. issue_line = response.body.chomp.
  869. split("\n").map {|line| line.split(',')}.
  870. detect {|line| line[0]==issue.id.to_s}
  871. assert_include '185.60', issue_line
  872. end
  873. end
  874. def test_index_csv_should_fill_parent_column_with_parent_id
  875. Issue.delete_all
  876. parent = Issue.generate!
  877. child = Issue.generate!(:parent_issue_id => parent.id)
  878. with_settings :default_language => 'en' do
  879. get(
  880. :index,
  881. :params => {
  882. :format => 'csv',
  883. :c => %w(parent)
  884. }
  885. )
  886. end
  887. lines = response.body.split("\n")
  888. assert_include "#{child.id},#{parent.id}", lines
  889. end
  890. def test_index_csv_big_5
  891. with_settings :default_language => "zh-TW" do
  892. str_utf8 = '一月'
  893. str_big5 = (+"\xa4@\xa4\xeb").force_encoding('Big5')
  894. issue = Issue.generate!(:subject => str_utf8)
  895. get(
  896. :index, :params => {
  897. :project_id => 1,
  898. :subject => str_utf8,
  899. :format => 'csv'
  900. }
  901. )
  902. assert_equal 'text/csv', @response.media_type
  903. lines = @response.body.chomp.split("\n")
  904. header = lines[0]
  905. status = (+"\xaa\xac\xbaA").force_encoding('Big5')
  906. assert_include status, header
  907. issue_line = lines.find {|l| l =~ /^#{issue.id},/}
  908. assert_include str_big5, issue_line
  909. end
  910. end
  911. def test_index_csv_cannot_convert_should_be_replaced_big_5
  912. with_settings :default_language => "zh-TW" do
  913. str_utf8 = '以内'
  914. issue = Issue.generate!(:subject => str_utf8)
  915. get(
  916. :index, :params => {
  917. :project_id => 1,
  918. :subject => str_utf8,
  919. :c => ['status', 'subject'],
  920. :format => 'csv',
  921. :set_filter => 1
  922. }
  923. )
  924. assert_equal 'text/csv', @response.media_type
  925. lines = @response.body.chomp.split("\n")
  926. header = lines[0]
  927. issue_line = lines.find {|l| l =~ /^#{issue.id},/}
  928. s1 = (+"\xaa\xac\xbaA").force_encoding('Big5') # status
  929. assert header.include?(s1)
  930. s2 = issue_line.split(",")[2]
  931. s3 = (+"\xa5H?").force_encoding('Big5') # subject
  932. assert_equal s3, s2
  933. end
  934. end
  935. def test_index_csv_tw
  936. with_settings :default_language => "zh-TW" do
  937. str1 = "test_index_csv_tw"
  938. issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
  939. get(
  940. :index,
  941. :params => {
  942. :project_id => 1,
  943. :subject => str1,
  944. :c => ['estimated_hours', 'subject'],
  945. :format => 'csv',
  946. :set_filter => 1
  947. }
  948. )
  949. assert_equal 'text/csv', @response.media_type
  950. lines = @response.body.chomp.split("\n")
  951. assert_include "#{issue.id},1234.50,#{str1}", lines
  952. end
  953. end
  954. def test_index_csv_fr
  955. with_settings :default_language => "fr" do
  956. str1 = "test_index_csv_fr"
  957. issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
  958. get(
  959. :index,
  960. :params => {
  961. :project_id => 1,
  962. :subject => str1,
  963. :c => ['estimated_hours', 'subject'],
  964. :format => 'csv',
  965. :set_filter => 1
  966. }
  967. )
  968. assert_equal 'text/csv', @response.media_type
  969. lines = @response.body.chomp.split("\n")
  970. assert_include "#{issue.id};1234,50;#{str1}", lines
  971. end
  972. end
  973. def test_index_csv_should_not_change_selected_columns
  974. get(
  975. :index,
  976. :params => {
  977. :set_filter => 1,
  978. :c => ["subject", "due_date"],
  979. :project_id => "ecookbook"
  980. }
  981. )
  982. assert_response :success
  983. assert_equal [:subject, :due_date], session[:issue_query][:column_names]
  984. get(
  985. :index,
  986. :params => {
  987. :set_filter => 1,
  988. :c =>["all_inline"],
  989. :project_id => "ecookbook",
  990. :format => 'csv'
  991. }
  992. )
  993. assert_response :success
  994. assert_equal [:subject, :due_date], session[:issue_query][:column_names]
  995. end
  996. def test_index_pdf
  997. ["en", "zh", "zh-TW", "ja", "ko", "ar"].each do |lang|
  998. with_settings :default_language => lang do
  999. get :index
  1000. assert_response :success
  1001. get(:index, :params => {:format => 'pdf'})
  1002. assert_response :success
  1003. assert_equal 'application/pdf', @response.media_type
  1004. get(
  1005. :index,
  1006. :params => {
  1007. :project_id => 1,
  1008. :format => 'pdf'
  1009. }
  1010. )
  1011. assert_response :success
  1012. assert_equal 'application/pdf', @response.media_type
  1013. get(
  1014. :index,
  1015. :params => {
  1016. :project_id => 1,
  1017. :query_id => 6,
  1018. :format => 'pdf'
  1019. }
  1020. )
  1021. assert_response :success
  1022. assert_equal 'application/pdf', @response.media_type
  1023. end
  1024. end
  1025. end
  1026. def test_index_pdf_with_query_grouped_by_list_custom_field
  1027. get(
  1028. :index,
  1029. :params => {
  1030. :project_id => 1,
  1031. :query_id => 9,
  1032. :format => 'pdf'
  1033. }
  1034. )
  1035. assert_response :success
  1036. assert_equal 'application/pdf', @response.media_type
  1037. end
  1038. def test_index_atom
  1039. with_settings :protocol => 'https', :host_name => 'example.net' do
  1040. get(
  1041. :index,
  1042. :params => {
  1043. :project_id => 'ecookbook',
  1044. :format => 'atom'
  1045. }
  1046. )
  1047. end
  1048. assert_response :success
  1049. assert_equal 'application/atom+xml', response.media_type
  1050. assert_select 'feed' do
  1051. assert_select 'link[rel=self][href=?]', 'https://example.net/projects/ecookbook/issues.atom'
  1052. assert_select 'link[rel=alternate][href=?]', 'https://example.net/projects/ecookbook/issues'
  1053. assert_select 'entry link[href=?]', 'https://example.net/issues/1'
  1054. end
  1055. end
  1056. def test_index_should_include_back_url_input
  1057. get(
  1058. :index,
  1059. :params => {
  1060. :project_id => 'ecookbook',
  1061. :foo => 'bar'
  1062. }
  1063. )
  1064. assert_response :success
  1065. assert_select 'input[name=back_url][value=?]', '/projects/ecookbook/issues?foo=bar'
  1066. end
  1067. def test_index_sort
  1068. get(:index, :params => {:sort => 'tracker,id:desc'})
  1069. assert_response :success
  1070. assert_equal(
  1071. issues_in_list.sort_by {|issue| [issue.tracker.position, -issue.id]},
  1072. issues_in_list
  1073. )
  1074. assert_select 'table.issues.sort-by-tracker.sort-asc'
  1075. end
  1076. def test_index_sort_by_field_not_included_in_columns
  1077. with_settings :issue_list_default_columns => %w(subject author) do
  1078. get(:index, :params => {:sort => 'tracker'})
  1079. assert_response :success
  1080. end
  1081. end
  1082. def test_index_sort_by_assigned_to
  1083. get(:index, :params => {:sort => 'assigned_to'})
  1084. assert_response :success
  1085. assignees = issues_in_list.map(&:assigned_to).compact
  1086. assert_equal assignees.sort, assignees
  1087. assert_select 'table.issues.sort-by-assigned-to.sort-asc'
  1088. end
  1089. def test_index_sort_by_assigned_to_desc
  1090. get(:index, :params => {:sort => 'assigned_to:desc'})
  1091. assert_response :success
  1092. assignees = issues_in_list.map(&:assigned_to).compact
  1093. assert_equal assignees.sort.reverse, assignees
  1094. assert_select 'table.issues.sort-by-assigned-to.sort-desc'
  1095. end
  1096. def test_index_group_by_assigned_to
  1097. get(
  1098. :index,
  1099. :params => {
  1100. :group_by => 'assigned_to',
  1101. :sort => 'priority'
  1102. }
  1103. )
  1104. assert_response :success
  1105. end
  1106. def test_index_sort_by_author
  1107. get(
  1108. :index,
  1109. :params => {
  1110. :sort => 'author',
  1111. :c => ['author']
  1112. }
  1113. )
  1114. assert_response :success
  1115. authors = issues_in_list.map(&:author)
  1116. assert_equal authors.sort, authors
  1117. end
  1118. def test_index_sort_by_author_desc
  1119. get(:index, :params => {:sort => 'author:desc'})
  1120. assert_response :success
  1121. authors = issues_in_list.map(&:author)
  1122. assert_equal authors.sort.reverse, authors
  1123. end
  1124. def test_index_group_by_author
  1125. get(
  1126. :index,
  1127. :params => {
  1128. :group_by => 'author',
  1129. :sort => 'priority'
  1130. }
  1131. )
  1132. assert_response :success
  1133. end
  1134. def test_index_sort_by_last_updated_by
  1135. get(:index, :params => {:sort => 'last_updated_by'})
  1136. assert_response :success
  1137. assert_select 'table.issues.sort-by-last-updated-by.sort-asc'
  1138. end
  1139. def test_index_sort_by_last_updated_by_desc
  1140. get(:index, :params => {:sort => 'last_updated_by:desc'})
  1141. assert_response :success
  1142. assert_select 'table.issues.sort-by-last-updated-by.sort-desc'
  1143. end
  1144. def test_index_sort_by_spent_hours
  1145. get(:index, :params => {:sort => 'spent_hours:desc'})
  1146. assert_response :success
  1147. hours = issues_in_list.map(&:spent_hours)
  1148. assert_equal hours.sort.reverse, hours
  1149. end
  1150. def test_index_sort_by_spent_hours_should_sort_by_visible_spent_hours
  1151. TimeEntry.delete_all
  1152. TimeEntry.generate!(:issue => Issue.generate!(:project_id => 1), :hours => 3)
  1153. TimeEntry.generate!(:issue => Issue.generate!(:project_id => 3), :hours => 4)
  1154. get(
  1155. :index,
  1156. :params => {
  1157. :sort => "spent_hours:desc",
  1158. :c => ['subject', 'spent_hours']
  1159. }
  1160. )
  1161. assert_response :success
  1162. assert_equal ['4.00', '3.00', '0.00'], columns_values_in_list('spent_hours')[0..2]
  1163. Project.find(3).disable_module!(:time_tracking)
  1164. get(
  1165. :index,
  1166. :params => {
  1167. :sort => "spent_hours:desc",
  1168. :c => ['subject', 'spent_hours']
  1169. }
  1170. )
  1171. assert_response :success
  1172. assert_equal ['3.00', '0.00', '0.00'], columns_values_in_list('spent_hours')[0..2]
  1173. end
  1174. def test_index_sort_by_total_spent_hours
  1175. get(:index, :params => {:sort => 'total_spent_hours:desc'})
  1176. assert_response :success
  1177. hours = issues_in_list.map(&:total_spent_hours)
  1178. assert_equal hours.sort.reverse, hours
  1179. end
  1180. def test_index_sort_by_total_estimated_hours
  1181. get(:index, :params => {:sort => 'total_estimated_hours:desc'})
  1182. assert_response :success
  1183. hours = issues_in_list.map(&:total_estimated_hours)
  1184. # Removes nil because the position of NULL is database dependent
  1185. hours.compact!
  1186. assert_equal hours.sort.reverse, hours
  1187. end
  1188. def test_index_sort_by_user_custom_field
  1189. cf = IssueCustomField.
  1190. create!(
  1191. :name => 'User',
  1192. :is_for_all => true,
  1193. :tracker_ids => [1, 2, 3],
  1194. :field_format => 'user'
  1195. )
  1196. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  1197. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  1198. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  1199. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  1200. get(
  1201. :index,
  1202. :params => {
  1203. :project_id => 1,
  1204. :set_filter => 1,
  1205. :sort => "cf_#{cf.id},id"
  1206. }
  1207. )
  1208. assert_response :success
  1209. assert_equal(
  1210. [2, 3, 1],
  1211. issues_in_list.select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
  1212. )
  1213. end
  1214. def test_index_with_columns
  1215. columns = ['tracker', 'subject', 'assigned_to', 'buttons']
  1216. get(
  1217. :index,
  1218. :params => {
  1219. :set_filter => 1,
  1220. :c => columns
  1221. }
  1222. )
  1223. assert_response :success
  1224. # query should use specified columns + id and checkbox
  1225. assert_select 'table.issues thead' do
  1226. assert_select 'th', columns.size + 2
  1227. assert_select 'th.tracker'
  1228. assert_select 'th.subject'
  1229. assert_select 'th.assigned_to'
  1230. assert_select 'th.buttons'
  1231. end
  1232. # columns should be stored in session
  1233. assert_kind_of Hash, session[:issue_query]
  1234. assert_kind_of Array, session[:issue_query][:column_names]
  1235. assert_equal columns, session[:issue_query][:column_names].map(&:to_s)
  1236. # ensure only these columns are kept in the selected columns list
  1237. assert_select 'select[name=?] option', 'c[]' do
  1238. assert_select 'option', 3
  1239. assert_select 'option[value=tracker]'
  1240. assert_select 'option[value=project]', 0
  1241. end
  1242. end
  1243. def test_index_without_project_should_implicitly_add_project_column_to_default_columns
  1244. with_settings :issue_list_default_columns => ['tracker', 'subject', 'assigned_to'] do
  1245. get(:index, :params => {:set_filter => 1})
  1246. end
  1247. # query should use specified columns
  1248. assert_equal ["#", "Project", "Tracker", "Subject", "Assignee"], columns_in_issues_list
  1249. end
  1250. def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
  1251. with_settings :issue_list_default_columns => ['tracker', 'subject', 'assigned_to'] do
  1252. columns = ['id', 'tracker', 'subject', 'assigned_to']
  1253. get(
  1254. :index,
  1255. :params => {
  1256. :set_filter => 1,
  1257. :c => columns
  1258. }
  1259. )
  1260. end
  1261. # query should use specified columns
  1262. assert_equal ["#", "Tracker", "Subject", "Assignee"], columns_in_issues_list
  1263. end
  1264. def test_index_with_default_columns_should_respect_default_columns_order
  1265. columns = ['assigned_to', 'subject', 'status', 'tracker']
  1266. with_settings :issue_list_default_columns => columns do
  1267. get(
  1268. :index,
  1269. :params => {
  1270. :project_id => 1,
  1271. :set_filter => 1
  1272. }
  1273. )
  1274. assert_equal ["#", "Assignee", "Subject", "Status", "Tracker"], columns_in_issues_list
  1275. end
  1276. end
  1277. def test_index_with_custom_field_column
  1278. columns = %w(tracker subject cf_2)
  1279. get(
  1280. :index,
  1281. :params => {
  1282. :set_filter => 1,
  1283. :c => columns
  1284. }
  1285. )
  1286. assert_response :success
  1287. # query should use specified columns
  1288. assert_equal ["#", "Tracker", "Subject", "Searchable field"], columns_in_issues_list
  1289. assert_select 'table.issues' do
  1290. assert_select 'th.cf_2.string'
  1291. assert_select 'td.cf_2.string'
  1292. end
  1293. end
  1294. def test_index_with_multi_custom_field_column
  1295. field = CustomField.find(1)
  1296. field.update_attribute :multiple, true
  1297. issue = Issue.find(1)
  1298. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  1299. issue.save!
  1300. get(
  1301. :index,
  1302. :params => {
  1303. :set_filter => 1,
  1304. :c => %w(tracker subject cf_1)
  1305. }
  1306. )
  1307. assert_response :success
  1308. assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
  1309. end
  1310. def test_index_with_multi_user_custom_field_column
  1311. field =
  1312. IssueCustomField.
  1313. create!(
  1314. :name => 'Multi user', :field_format => 'user',
  1315. :multiple => true,
  1316. :tracker_ids => [1], :is_for_all => true
  1317. )
  1318. issue = Issue.find(1)
  1319. issue.custom_field_values = {field.id => ['2', '3']}
  1320. issue.save!
  1321. get(
  1322. :index,
  1323. :params => {
  1324. :set_filter => 1,
  1325. :c => ['tracker', 'subject', "cf_#{field.id}"]
  1326. }
  1327. )
  1328. assert_response :success
  1329. assert_select "table.issues td.cf_#{field.id}" do
  1330. assert_select 'a', 2
  1331. assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
  1332. assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
  1333. end
  1334. end
  1335. def test_index_with_date_column
  1336. with_settings :date_format => '%d/%m/%Y' do
  1337. Issue.find(1).update_attribute :start_date, '1987-08-24'
  1338. get(
  1339. :index,
  1340. :params => {
  1341. :set_filter => 1,
  1342. :c => %w(start_date)
  1343. }
  1344. )
  1345. assert_select 'table.issues' do
  1346. assert_select 'th.start_date'
  1347. assert_select 'td.start_date', :text => '24/08/1987'
  1348. end
  1349. end
  1350. end
  1351. def test_index_with_done_ratio_column
  1352. Issue.find(1).update_attribute :done_ratio, 40
  1353. get(
  1354. :index,
  1355. :params => {
  1356. :set_filter => 1,
  1357. :c => %w(done_ratio)
  1358. }
  1359. )
  1360. assert_select 'table.issues td.done_ratio' do
  1361. assert_select 'table.progress' do
  1362. assert_select 'td.closed[style=?]', 'width: 40%;'
  1363. end
  1364. end
  1365. end
  1366. def test_index_with_spent_hours_column
  1367. Issue.expects(:load_visible_spent_hours).once
  1368. get(
  1369. :index,
  1370. :params => {
  1371. :set_filter => 1,
  1372. :c => %w(subject spent_hours)
  1373. }
  1374. )
  1375. assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
  1376. end
  1377. def test_index_with_total_spent_hours_column
  1378. Issue.expects(:load_visible_total_spent_hours).once
  1379. get(
  1380. :index,
  1381. :params => {
  1382. :set_filter => 1,
  1383. :c => %w(subject total_spent_hours)
  1384. }
  1385. )
  1386. assert_select 'table.issues tr#issue-3 td.total_spent_hours', :text => '1.00'
  1387. end
  1388. def test_index_with_total_estimated_hours_column
  1389. get(
  1390. :index,
  1391. :params => {
  1392. :set_filter => 1,
  1393. :c => %w(subject total_estimated_hours)
  1394. }
  1395. )
  1396. assert_select 'table.issues td.total_estimated_hours'
  1397. end
  1398. def test_index_should_not_show_spent_hours_column_without_permission
  1399. Role.anonymous.remove_permission! :view_time_entries
  1400. get(
  1401. :index,
  1402. :params => {
  1403. :set_filter => 1,
  1404. :c => %w(subject spent_hours)
  1405. }
  1406. )
  1407. assert_select 'td.spent_hours', 0
  1408. end
  1409. def test_index_with_fixed_version_column
  1410. get(
  1411. :index,
  1412. :params => {
  1413. :set_filter => 1,
  1414. :c => %w(fixed_version)
  1415. }
  1416. )
  1417. assert_select 'table.issues td.fixed_version' do
  1418. assert_select 'a[href=?]', '/versions/2', :text => 'eCookbook - 1.0'
  1419. end
  1420. end
  1421. def test_index_with_relations_column
  1422. IssueRelation.delete_all
  1423. IssueRelation.
  1424. create!(
  1425. :relation_type => "relates",
  1426. :issue_from => Issue.find(1), :issue_to => Issue.find(7)
  1427. )
  1428. IssueRelation.
  1429. create!(
  1430. :relation_type => "relates",
  1431. :issue_from => Issue.find(8), :issue_to => Issue.find(1)
  1432. )
  1433. IssueRelation.
  1434. create!(
  1435. :relation_type => "blocks",
  1436. :issue_from => Issue.find(1), :issue_to => Issue.find(11)
  1437. )
  1438. IssueRelation.
  1439. create!(
  1440. :relation_type => "blocks", :issue_from => Issue.find(12),
  1441. :issue_to => Issue.find(2)
  1442. )
  1443. get(
  1444. :index,
  1445. :params => {
  1446. :set_filter => 1,
  1447. :c => %w(subject relations)
  1448. }
  1449. )
  1450. assert_response :success
  1451. assert_select "tr#issue-1 td.relations" do
  1452. assert_select "span", 3
  1453. assert_select "span", :text => "Related to #7"
  1454. assert_select "span", :text => "Related to #8"
  1455. assert_select "span", :text => "Blocks #11"
  1456. end
  1457. assert_select "tr#issue-2 td.relations" do
  1458. assert_select "span", 1
  1459. assert_select "span", :text => "Blocked by #12"
  1460. end
  1461. assert_select "tr#issue-3 td.relations" do
  1462. assert_select "span", 0
  1463. end
  1464. get(
  1465. :index,
  1466. :params => {
  1467. :set_filter => 1,
  1468. :c => %w(relations),
  1469. :format => 'csv'
  1470. }
  1471. )
  1472. assert_response :success
  1473. assert_equal 'text/csv', response.media_type
  1474. lines = response.body.chomp.split("\n")
  1475. assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
  1476. assert_include '2,Blocked by #12', lines
  1477. assert_include '3,""', lines
  1478. get(
  1479. :index,
  1480. :params => {
  1481. :set_filter => 1,
  1482. :c => %w(subject relations),
  1483. :format => 'pdf'
  1484. }
  1485. )
  1486. assert_response :success
  1487. assert_equal 'application/pdf', response.media_type
  1488. end
  1489. def test_index_with_description_column
  1490. get(
  1491. :index,
  1492. :params => {
  1493. :set_filter => 1,
  1494. :c => %w(subject description)
  1495. }
  1496. )
  1497. assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
  1498. assert_select 'td.description[colspan="4"]', :text => 'Unable to print recipes'
  1499. get(
  1500. :index,
  1501. :params => {
  1502. :set_filter => 1,
  1503. :c => %w(subject description),
  1504. :format => 'pdf'
  1505. }
  1506. )
  1507. assert_response :success
  1508. assert_equal 'application/pdf', response.media_type
  1509. end
  1510. def test_index_with_last_notes_column
  1511. get(
  1512. :index,
  1513. :params => {
  1514. :set_filter => 1,
  1515. :c => %w(subject last_notes)
  1516. }
  1517. )
  1518. assert_response :success
  1519. assert_select 'table.issues thead th', 4 # columns: chekbox + id + subject
  1520. assert_select 'td.last_notes[colspan="4"]', :text => 'Some notes with Redmine links: #2, r2.'
  1521. assert_select(
  1522. 'td.last_notes[colspan="4"]',
  1523. :text => 'A comment with inline image: and a reference to #1 and r2.'
  1524. )
  1525. get(
  1526. :index,
  1527. :params => {
  1528. :set_filter => 1,
  1529. :c => %w(subject last_notes),
  1530. :format => 'pdf'
  1531. }
  1532. )
  1533. assert_response :success
  1534. assert_equal 'application/pdf', response.media_type
  1535. end
  1536. def test_index_with_last_notes_column_should_display_private_notes_with_permission_only
  1537. journal = Journal.
  1538. create!(
  1539. :journalized => Issue.find(2),
  1540. :notes => 'Public notes', :user_id => 1
  1541. )
  1542. journal = Journal.
  1543. create!(
  1544. :journalized => Issue.find(2),
  1545. :notes => 'Privates notes', :private_notes => true,
  1546. :user_id => 1
  1547. )
  1548. @request.session[:user_id] = 2
  1549. get(
  1550. :index,
  1551. :params => {
  1552. :set_filter => 1,
  1553. :c => %w(subject last_notes)
  1554. }
  1555. )
  1556. assert_response :success
  1557. assert_select 'td.last_notes[colspan="4"]', :text => 'Privates notes'
  1558. Role.find(1).remove_permission! :view_private_notes
  1559. get(
  1560. :index,
  1561. :params => {
  1562. :set_filter => 1,
  1563. :c => %w(subject last_notes)
  1564. }
  1565. )
  1566. assert_response :success
  1567. assert_select 'td.last_notes[colspan="4"]', :text => 'Public notes'
  1568. end
  1569. def test_index_with_description_and_last_notes_columns_should_display_column_name
  1570. get(
  1571. :index,
  1572. :params => {
  1573. :set_filter => 1,
  1574. :c => %w(subject last_notes description)
  1575. }
  1576. )
  1577. assert_response :success
  1578. assert_select 'td.last_notes[colspan="4"] span', :text => 'Last notes'
  1579. assert_select 'td.description[colspan="4"] span', :text => 'Description'
  1580. end
  1581. def test_index_with_full_width_layout_custom_field_column_should_show_column_as_block_column
  1582. field = IssueCustomField.
  1583. create!(
  1584. :name => 'Long text', :field_format => 'text',
  1585. :full_width_layout => '1',
  1586. :tracker_ids => [1], :is_for_all => true
  1587. )
  1588. issue = Issue.find(1)
  1589. issue.custom_field_values = {field.id => 'This is a long text'}
  1590. issue.save!
  1591. get(
  1592. :index,
  1593. :params => {
  1594. :set_filter => 1,
  1595. :c => ['subject', 'description', "cf_#{field.id}"]
  1596. }
  1597. )
  1598. assert_response :success
  1599. assert_select 'td.description[colspan="4"] span', :text => 'Description'
  1600. assert_select "td.cf_#{field.id} span", :text => 'Long text'
  1601. end
  1602. def test_index_with_parent_column
  1603. Issue.delete_all
  1604. parent = Issue.generate!
  1605. child = Issue.generate!(:parent_issue_id => parent.id)
  1606. get(:index, :params => {:c => %w(parent)})
  1607. assert_select 'td.parent', :text => "#{parent.tracker} ##{parent.id}"
  1608. assert_select 'td.parent a[title=?]', parent.subject
  1609. end
  1610. def test_index_with_parent_subject_column
  1611. Issue.delete_all
  1612. parent = Issue.generate!
  1613. child = Issue.generate!(:parent_issue_id => parent.id)
  1614. get(:index, :params => {:c => %w(parent.subject)})
  1615. assert_select 'table.issues' do
  1616. assert_select 'th.parent-subject', :text => l(:field_parent_issue_subject)
  1617. assert_select "tr#issue-#{child.id}" do
  1618. assert_select 'td.parent-subject', :text => parent.subject
  1619. end
  1620. end
  1621. end
  1622. def test_index_with_last_updated_by_column
  1623. get(
  1624. :index, :params => {
  1625. :c => %w(subject last_updated_by),
  1626. :issue_id => '1,2,3',
  1627. :sort => 'id',
  1628. :set_filter => '1'
  1629. }
  1630. )
  1631. assert_select 'td.last_updated_by'
  1632. assert_equal ["John Smith", "John Smith", ""], css_select('td.last_updated_by').map(&:text)
  1633. end
  1634. def test_index_with_attachments_column
  1635. get(
  1636. :index,
  1637. :params => {
  1638. :c => %w(subject attachments),
  1639. :set_filter => '1',
  1640. :sort => 'id'
  1641. }
  1642. )
  1643. assert_response :success
  1644. assert_select 'td.attachments'
  1645. assert_select 'tr#issue-2' do
  1646. assert_select 'td.attachments' do
  1647. assert_select 'span:nth-of-type(1)' do
  1648. assert_select 'a[href=?]', '/attachments/4', :text => 'source.rb'
  1649. assert_select 'a[href=?].icon-download', '/attachments/download/4/source.rb'
  1650. end
  1651. assert_select 'span:nth-of-type(2)' do
  1652. assert_select 'a[href=?]', '/attachments/10', :text => 'picture.jpg'
  1653. assert_select 'a[href=?].icon-download', '/attachments/download/10/picture.jpg'
  1654. end
  1655. end
  1656. end
  1657. end
  1658. def test_index_with_attachments_column_as_csv
  1659. get(
  1660. :index,
  1661. :params => {
  1662. :c => %w(subject attachments),
  1663. :set_filter => '1',
  1664. :sort => 'id',
  1665. :format => 'csv'
  1666. }
  1667. )
  1668. assert_response :success
  1669. assert_include "\"source.rb\npicture.jpg\"", response.body
  1670. end
  1671. def test_index_with_estimated_hours_total
  1672. Issue.delete_all
  1673. Issue.generate!(:estimated_hours => 5.5)
  1674. Issue.generate!(:estimated_hours => 1.1)
  1675. get(:index, :params => {:t => %w(estimated_hours)})
  1676. assert_response :success
  1677. assert_select '.query-totals'
  1678. assert_select '.total-for-estimated-hours span.value', :text => '6.60'
  1679. assert_select 'input[type=checkbox][name=?][value=estimated_hours][checked=checked]', 't[]'
  1680. end
  1681. def test_index_with_grouped_query_and_estimated_hours_total
  1682. Issue.delete_all
  1683. Issue.generate!(:estimated_hours => 5.5, :category_id => 1)
  1684. Issue.generate!(:estimated_hours => 2.3, :category_id => 1)
  1685. Issue.generate!(:estimated_hours => 1.1, :category_id => 2)
  1686. Issue.generate!(:estimated_hours => 4.6)
  1687. get(
  1688. :index,
  1689. :params => {
  1690. :t => %w(estimated_hours),
  1691. :group_by => 'category'
  1692. }
  1693. )
  1694. assert_response :success
  1695. assert_select '.query-totals'
  1696. assert_select '.query-totals .total-for-estimated-hours span.value', :text => '13.50'
  1697. assert_select 'tr.group', :text => /Printing/ do
  1698. assert_select '.total-for-estimated-hours span.value', :text => '7.80'
  1699. end
  1700. assert_select 'tr.group', :text => /Recipes/ do
  1701. assert_select '.total-for-estimated-hours span.value', :text => '1.10'
  1702. end
  1703. assert_select 'tr.group', :text => /blank/ do
  1704. assert_select '.total-for-estimated-hours span.value', :text => '4.60'
  1705. end
  1706. end
  1707. def test_index_with_int_custom_field_total
  1708. field = IssueCustomField.generate!(:field_format => 'int', :is_for_all => true)
  1709. CustomValue.create!(:customized => Issue.find(1), :custom_field => field, :value => '2')
  1710. CustomValue.create!(:customized => Issue.find(2), :custom_field => field, :value => '7')
  1711. get(:index, :params => {:t => ["cf_#{field.id}"]})
  1712. assert_response :success
  1713. assert_select '.query-totals'
  1714. assert_select ".total-for-cf-#{field.id} span.value", :text => '9'
  1715. end
  1716. def test_index_with_spent_time_total_should_sum_visible_spent_time_only
  1717. TimeEntry.delete_all
  1718. TimeEntry.generate!(:issue => Issue.generate!(:project_id => 1), :hours => 3)
  1719. TimeEntry.generate!(:issue => Issue.generate!(:project_id => 3), :hours => 4)
  1720. get :index, :params => {:t => ["spent_hours"]}
  1721. assert_response :success
  1722. assert_select ".total-for-spent-hours span.value", :text => '7.00'
  1723. Project.find(3).disable_module!(:time_tracking)
  1724. get :index, :params => {:t => ["spent_hours"]}
  1725. assert_response :success
  1726. assert_select ".total-for-spent-hours span.value", :text => '3.00'
  1727. end
  1728. def test_index_totals_should_default_to_settings
  1729. with_settings :issue_list_default_totals => ['estimated_hours'] do
  1730. get :index
  1731. assert_response :success
  1732. assert_select '.total-for-estimated-hours span.value'
  1733. assert_select '.query-totals>span', 1
  1734. end
  1735. end
  1736. def test_index_send_html_if_query_is_invalid
  1737. get(
  1738. :index,
  1739. :params => {
  1740. :f => ['start_date'],
  1741. :op => {
  1742. :start_date => '='
  1743. }
  1744. }
  1745. )
  1746. assert_equal 'text/html', @response.media_type
  1747. assert_select_error /Start date cannot be blank/i
  1748. end
  1749. def test_index_send_nothing_if_query_is_invalid
  1750. get(
  1751. :index,
  1752. :params => {
  1753. :f => ['start_date'],
  1754. :op => {
  1755. :start_date => '='
  1756. },
  1757. :format => 'csv'
  1758. }
  1759. )
  1760. assert_equal 'text/csv', @response.media_type
  1761. assert @response.body.blank?
  1762. end
  1763. def test_index_should_include_new_issue_link
  1764. @request.session[:user_id] = 2
  1765. get(:index, :params => {:project_id => 1})
  1766. assert_select(
  1767. '#content a.new-issue[href="/projects/ecookbook/issues/new"]',
  1768. :text => 'New issue'
  1769. )
  1770. end
  1771. def test_index_should_not_include_new_issue_link_for_project_without_trackers
  1772. Project.find(1).trackers.clear
  1773. @request.session[:user_id] = 2
  1774. get(:index, :params => {:project_id => 1})
  1775. assert_select '#content a.new-issue', 0
  1776. end
  1777. def test_index_should_not_include_new_issue_link_for_users_with_copy_issues_permission_only
  1778. role = Role.find(1)
  1779. role.remove_permission! :add_issues
  1780. role.add_permission! :copy_issues
  1781. @request.session[:user_id] = 2
  1782. get(:index, :params => {:project_id => 1})
  1783. assert_select '#content a.new-issue', 0
  1784. end
  1785. def test_index_without_project_should_include_new_issue_link
  1786. @request.session[:user_id] = 2
  1787. get :index
  1788. assert_select '#content a.new-issue[href="/issues/new"]', :text => 'New issue'
  1789. end
  1790. def test_index_should_not_include_new_issue_tab_when_disabled
  1791. with_settings :new_item_menu_tab => '0' do
  1792. @request.session[:user_id] = 2
  1793. get(:index, :params => {:project_id => 1})
  1794. assert_select '#main-menu a.new-issue', 0
  1795. end
  1796. end
  1797. def test_index_should_include_new_issue_tab_when_enabled
  1798. with_settings :new_item_menu_tab => '1' do
  1799. @request.session[:user_id] = 2
  1800. get(:index, :params => {:project_id => 1})
  1801. assert_select(
  1802. '#main-menu a.new-issue[href="/projects/ecookbook/issues/new"]',
  1803. :text => 'New issue'
  1804. )
  1805. end
  1806. end
  1807. def test_new_should_have_new_issue_tab_as_current_menu_item
  1808. with_settings :new_item_menu_tab => '1' do
  1809. @request.session[:user_id] = 2
  1810. get(:new, :params => {:project_id => 1})
  1811. assert_select '#main-menu a.new-issue.selected'
  1812. end
  1813. end
  1814. def test_index_should_not_include_new_issue_tab_for_project_without_trackers
  1815. with_settings :new_item_menu_tab => '1' do
  1816. Project.find(1).trackers.clear
  1817. @request.session[:user_id] = 2
  1818. get(:index, :params => {:project_id => 1})
  1819. assert_select '#main-menu a.new-issue', 0
  1820. end
  1821. end
  1822. def test_index_should_not_include_new_issue_tab_for_users_with_copy_issues_permission_only
  1823. with_settings :new_item_menu_tab => '1' do
  1824. role = Role.find(1)
  1825. role.remove_permission! :add_issues
  1826. role.add_permission! :copy_issues
  1827. @request.session[:user_id] = 2
  1828. get(:index, :params => {:project_id => 1})
  1829. assert_select '#main-menu a.new-issue', 0
  1830. end
  1831. end
  1832. def test_index_should_respect_timespan_format
  1833. with_settings :timespan_format => 'minutes' do
  1834. get(
  1835. :index,
  1836. :params => {
  1837. :set_filter => 1,
  1838. :c => %w(estimated_hours total_estimated_hours spent_hours total_spent_hours)
  1839. }
  1840. )
  1841. assert_select 'table.issues tr#issue-1 td.estimated_hours', :text => '200:00'
  1842. assert_select 'table.issues tr#issue-1 td.total_estimated_hours', :text => '200:00'
  1843. assert_select 'table.issues tr#issue-1 td.spent_hours', :text => '154:15'
  1844. assert_select 'table.issues tr#issue-1 td.total_spent_hours', :text => '154:15'
  1845. end
  1846. end
  1847. def test_show_by_anonymous
  1848. get(:show, :params => {:id => 1})
  1849. assert_response :success
  1850. assert_select 'div.issue div.description', :text => /Unable to print recipes/
  1851. # anonymous role is allowed to add a note
  1852. assert_select 'form#issue-form' do
  1853. assert_select 'fieldset' do
  1854. assert_select 'legend', :text => 'Notes'
  1855. assert_select 'textarea[name=?]', 'issue[notes]'
  1856. end
  1857. end
  1858. assert_select 'title', :text => "Bug #1: Cannot print recipes - eCookbook - Redmine"
  1859. end
  1860. def test_show_by_manager
  1861. @request.session[:user_id] = 2
  1862. get(:show, :params => {:id => 1})
  1863. assert_select 'a', :text => /Quote/
  1864. assert_select 'form#issue-form' do
  1865. assert_select 'fieldset' do
  1866. assert_select 'legend', :text => 'Change properties'
  1867. assert_select 'input[name=?]', 'issue[subject]'
  1868. end
  1869. assert_select 'fieldset' do
  1870. assert_select 'legend', :text => 'Log time'
  1871. assert_select 'input[name=?]', 'time_entry[hours]'
  1872. end
  1873. assert_select 'fieldset' do
  1874. assert_select 'legend', :text => 'Notes'
  1875. assert_select 'textarea[name=?]', 'issue[notes]'
  1876. end
  1877. end
  1878. end
  1879. def test_show_should_display_update_form
  1880. @request.session[:user_id] = 2
  1881. get(:show, :params => {:id => 1})
  1882. assert_response :success
  1883. assert_select 'form#issue-form' do
  1884. assert_select 'input[name=?]', 'issue[is_private]'
  1885. assert_select 'select[name=?]', 'issue[project_id]'
  1886. assert_select 'select[name=?]', 'issue[tracker_id]'
  1887. assert_select 'input[name=?]', 'issue[subject]'
  1888. assert_select 'textarea[name=?]', 'issue[description]'
  1889. assert_select 'select[name=?]', 'issue[status_id]'
  1890. assert_select 'select[name=?]', 'issue[priority_id]'
  1891. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  1892. assert_select 'select[name=?]', 'issue[category_id]'
  1893. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  1894. assert_select 'input[name=?]', 'issue[parent_issue_id]'
  1895. assert_select 'input[name=?]', 'issue[start_date]'
  1896. assert_select 'input[name=?]', 'issue[due_date]'
  1897. assert_select 'select[name=?]', 'issue[done_ratio]'
  1898. assert_select 'input[name=?]', 'issue[custom_field_values][2]'
  1899. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  1900. assert_select 'textarea[name=?]', 'issue[notes]'
  1901. end
  1902. end
  1903. def test_show_should_display_update_form_with_minimal_permissions
  1904. Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
  1905. WorkflowTransition.where(:role_id => 1).delete_all
  1906. @request.session[:user_id] = 2
  1907. get(:show, :params => {:id => 1})
  1908. assert_response :success
  1909. assert_select 'form#issue-form' do
  1910. assert_select 'input[name=?]', 'issue[is_private]', 0
  1911. assert_select 'select[name=?]', 'issue[project_id]', 0
  1912. assert_select 'select[name=?]', 'issue[tracker_id]', 0
  1913. assert_select 'input[name=?]', 'issue[subject]', 0
  1914. assert_select 'textarea[name=?]', 'issue[description]', 0
  1915. assert_select 'select[name=?]', 'issue[status_id]', 0
  1916. assert_select 'select[name=?]', 'issue[priority_id]', 0
  1917. assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
  1918. assert_select 'select[name=?]', 'issue[category_id]', 0
  1919. assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
  1920. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  1921. assert_select 'input[name=?]', 'issue[start_date]', 0
  1922. assert_select 'input[name=?]', 'issue[due_date]', 0
  1923. assert_select 'select[name=?]', 'issue[done_ratio]', 0
  1924. assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
  1925. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  1926. assert_select 'textarea[name=?]', 'issue[notes]'
  1927. end
  1928. end
  1929. def test_show_should_not_display_update_form_without_permissions
  1930. Role.find(1).update_attribute :permissions, [:view_issues]
  1931. @request.session[:user_id] = 2
  1932. get(:show, :params => {:id => 1})
  1933. assert_response :success
  1934. assert_select 'form#issue-form', 0
  1935. end
  1936. def test_update_form_should_not_display_inactive_enumerations
  1937. assert !IssuePriority.find(15).active?
  1938. @request.session[:user_id] = 2
  1939. get(:show, :params => {:id => 1})
  1940. assert_response :success
  1941. assert_select 'form#issue-form' do
  1942. assert_select 'select[name=?]', 'issue[priority_id]' do
  1943. assert_select 'option[value="4"]'
  1944. assert_select 'option[value="15"]', 0
  1945. end
  1946. end
  1947. end
  1948. def test_update_form_should_allow_attachment_upload
  1949. @request.session[:user_id] = 2
  1950. get(:show, :params => {:id => 1})
  1951. assert_select 'form#issue-form[method=post][enctype="multipart/form-data"]' do
  1952. assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
  1953. end
  1954. end
  1955. def test_update_form_should_render_assign_to_me_link_when_issue_can_be_assigned_to_the_current_user
  1956. @request.session[:user_id] = 1
  1957. get(
  1958. :show,
  1959. :params => {
  1960. :id => 10
  1961. }
  1962. )
  1963. assert_select 'form#issue-form #attributes' do
  1964. assert_select 'a[class=?][data-id=?]', 'assign-to-me-link', '1', 1
  1965. end
  1966. end
  1967. def test_update_form_should_not_render_assign_to_me_link_when_issue_cannot_be_assigned_to_the_current_user
  1968. @request.session[:user_id] = 1
  1969. get(
  1970. :show,
  1971. :params => {
  1972. :id => 2
  1973. }
  1974. )
  1975. assert_select 'form#issue-form #attributes' do
  1976. assert_select 'a[class=?]', 'assign-to-me-link', 0
  1977. end
  1978. end
  1979. def test_update_form_should_not_show_assign_to_me_link_when_issue_is_assigned_to_the_current_user
  1980. issue = Issue.find(10)
  1981. issue.assigned_to_id = 1
  1982. issue.save!
  1983. @request.session[:user_id] = 1
  1984. get(
  1985. :show,
  1986. :params => {
  1987. :id => 10
  1988. }
  1989. )
  1990. assert_select 'form#issue-form #attributes' do
  1991. assert_select 'a[class=?]', 'assign-to-me-link hidden', 1
  1992. end
  1993. end
  1994. def test_show_should_deny_anonymous_access_without_permission
  1995. Role.anonymous.remove_permission!(:view_issues)
  1996. get(:show, :params => {:id => 1})
  1997. assert_response :redirect
  1998. end
  1999. def test_show_should_deny_anonymous_access_to_private_issue
  2000. Issue.where(:id => 1).update_all(["is_private = ?", true])
  2001. get(:show, :params => {:id => 1})
  2002. assert_response :redirect
  2003. end
  2004. def test_show_should_deny_non_member_access_without_permission
  2005. Role.non_member.remove_permission!(:view_issues)
  2006. @request.session[:user_id] = 9
  2007. get(:show, :params => {:id => 1})
  2008. assert_response 403
  2009. end
  2010. def test_show_should_deny_non_member_access_to_private_issue
  2011. Issue.where(:id => 1).update_all(["is_private = ?", true])
  2012. @request.session[:user_id] = 9
  2013. get(:show, :params => {:id => 1})
  2014. assert_response 403
  2015. end
  2016. def test_show_should_deny_member_access_without_permission
  2017. Role.find(1).remove_permission!(:view_issues)
  2018. @request.session[:user_id] = 2
  2019. get(:show, :params => {:id => 1})
  2020. assert_response 403
  2021. end
  2022. def test_show_should_deny_member_access_to_private_issue_without_permission
  2023. Issue.where(:id => 1).update_all(["is_private = ?", true])
  2024. @request.session[:user_id] = 3
  2025. get(:show, :params => {:id => 1})
  2026. assert_response 403
  2027. end
  2028. def test_show_should_allow_author_access_to_private_issue
  2029. Issue.where(:id => 1).update_all(["is_private = ?, author_id = 3", true])
  2030. @request.session[:user_id] = 3
  2031. get(:show, :params => {:id => 1})
  2032. assert_response :success
  2033. end
  2034. def test_show_should_allow_assignee_access_to_private_issue
  2035. Issue.where(:id => 1).update_all(["is_private = ?, assigned_to_id = 3", true])
  2036. @request.session[:user_id] = 3
  2037. get(:show, :params => {:id => 1})
  2038. assert_response :success
  2039. end
  2040. def test_show_should_allow_member_access_to_private_issue_with_permission
  2041. Issue.where(:id => 1).update_all(["is_private = ?", true])
  2042. User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
  2043. @request.session[:user_id] = 3
  2044. get(:show, :params => {:id => 1})
  2045. assert_response :success
  2046. end
  2047. def test_show_should_format_related_issues_dates
  2048. with_settings :date_format => '%d/%m/%Y' do
  2049. issue = Issue.generate!(:start_date => '2018-11-29', :due_date => '2018-12-01')
  2050. IssueRelation.
  2051. create!(
  2052. :issue_from => Issue.find(1), :issue_to => issue,
  2053. :relation_type => 'relates'
  2054. )
  2055. get(:show, :params => {:id => 1})
  2056. assert_response :success
  2057. assert_select '#relations td.start_date', :text => '29/11/2018'
  2058. assert_select '#relations td.due_date', :text => '01/12/2018'
  2059. end
  2060. end
  2061. def test_show_should_not_disclose_relations_to_invisible_issues
  2062. with_settings :cross_project_issue_relations => '1' do
  2063. IssueRelation.
  2064. create!(
  2065. :issue_from => Issue.find(1),
  2066. :issue_to => Issue.find(2),
  2067. :relation_type => 'relates'
  2068. )
  2069. # Relation to a private project issue
  2070. IssueRelation.
  2071. create!(
  2072. :issue_from => Issue.find(1),
  2073. :issue_to => Issue.find(4),
  2074. :relation_type => 'relates'
  2075. )
  2076. get(:show, :params => {:id => 1})
  2077. assert_response :success
  2078. assert_select 'div#relations' do
  2079. assert_select 'a', :text => /#2$/
  2080. assert_select 'a', :text => /#4$/, :count => 0
  2081. end
  2082. end
  2083. end
  2084. def test_show_should_list_subtasks
  2085. Issue.
  2086. create!(
  2087. :project_id => 1, :author_id => 1, :tracker_id => 1,
  2088. :parent_issue_id => 1, :subject => 'Child Issue'
  2089. )
  2090. get(:show, :params => {:id => 1})
  2091. assert_response :success
  2092. assert_select 'div#issue_tree' do
  2093. assert_select 'td.subject', :text => /Child Issue/
  2094. end
  2095. end
  2096. def test_show_should_list_parents
  2097. issue = Issue.
  2098. create!(
  2099. :project_id => 1, :author_id => 1,
  2100. :tracker_id => 1, :parent_issue_id => 1,
  2101. :subject => 'Child Issue'
  2102. )
  2103. get(:show, :params => {:id => issue.id})
  2104. assert_response :success
  2105. assert_select 'div.subject' do
  2106. assert_select 'h3', 'Child Issue'
  2107. assert_select 'a[href="/issues/1"]'
  2108. end
  2109. end
  2110. def test_show_should_not_display_prev_next_links_without_query_in_session
  2111. get(:show, :params => {:id => 1})
  2112. assert_response :success
  2113. assert_select 'div.next-prev-links', 0
  2114. end
  2115. def test_show_should_display_prev_next_links_with_query_in_session
  2116. @request.session[:issue_query] =
  2117. {
  2118. :filters => {
  2119. 'status_id' => {
  2120. :values => [''], :operator => 'o'
  2121. }
  2122. },
  2123. :project_id => nil,
  2124. :sort => [['id', 'asc']]
  2125. }
  2126. with_settings :display_subprojects_issues => '0' do
  2127. get(:show, :params => {:id => 3})
  2128. end
  2129. assert_response :success
  2130. count = Issue.open.visible.count
  2131. # Previous and next issues for all projects
  2132. assert_select 'div.next-prev-links' do
  2133. assert_select 'a[href="/issues/2"]', :text => /Previous/
  2134. assert_select 'a[href="/issues/5"]', :text => /Next/
  2135. assert_select 'span.position', :text => "3 of #{count}"
  2136. end
  2137. end
  2138. def test_show_should_display_prev_next_links_with_saved_query_in_session
  2139. query =
  2140. IssueQuery.create!(
  2141. :name => 'test',
  2142. :visibility => IssueQuery::VISIBILITY_PUBLIC,
  2143. :user_id => 1,
  2144. :filters => {'status_id' => {:values => ['5'], :operator => '='}},
  2145. :sort_criteria => [['id', 'asc']]
  2146. )
  2147. @request.session[:issue_query] = {:id => query.id, :project_id => nil}
  2148. get(:show, :params => {:id => 11})
  2149. assert_response :success
  2150. # Previous and next issues for all projects
  2151. assert_select 'div.next-prev-links' do
  2152. assert_select 'a[href="/issues/8"]', :text => /Previous/
  2153. assert_select 'a[href="/issues/12"]', :text => /Next/
  2154. end
  2155. end
  2156. def test_show_should_display_prev_next_links_with_query_and_sort_on_association
  2157. @request.session[:issue_query] =
  2158. {
  2159. :filters => {
  2160. 'status_id' => {
  2161. :values => [''], :operator => 'o'
  2162. }
  2163. },
  2164. :project_id => nil
  2165. }
  2166. %w(project tracker status priority author assigned_to category fixed_version).
  2167. each do |assoc_sort|
  2168. @request.session[:issue_query][:sort] = [[assoc_sort, 'asc']]
  2169. get(:show, :params => {:id => 3})
  2170. assert_response :success, "Wrong response status for #{assoc_sort} sort"
  2171. assert_select 'div.next-prev-links' do
  2172. assert_select 'a', :text => /(Previous|Next)/
  2173. end
  2174. end
  2175. end
  2176. def test_show_should_display_prev_next_links_with_project_query_in_session
  2177. @request.session[:issue_query] =
  2178. {
  2179. :filters => {
  2180. 'status_id' => {:values => [''], :operator => 'o'}
  2181. },
  2182. :project_id => 1, :sort => [['id', 'asc']]
  2183. }
  2184. with_settings :display_subprojects_issues => '0' do
  2185. get(:show, :params => {:id => 3})
  2186. end
  2187. assert_response :success
  2188. # Previous and next issues inside project
  2189. assert_select 'div.next-prev-links' do
  2190. assert_select 'a[href="/issues/2"]', :text => /Previous/
  2191. assert_select 'a[href="/issues/7"]', :text => /Next/
  2192. end
  2193. end
  2194. def test_show_should_not_display_prev_link_for_first_issue
  2195. @request.session[:issue_query] =
  2196. {
  2197. :filters => {
  2198. 'status_id' => {:values => [''], :operator => 'o'}
  2199. },
  2200. :project_id => 1, :sort => [['id', 'asc']]
  2201. }
  2202. with_settings :display_subprojects_issues => '0' do
  2203. get(:show, :params => {:id => 1})
  2204. end
  2205. assert_response :success
  2206. assert_select 'div.next-prev-links' do
  2207. assert_select 'a', :text => /Previous/, :count => 0
  2208. assert_select 'a[href="/issues/2"]', :text => /Next/
  2209. end
  2210. end
  2211. def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
  2212. @request.session[:issue_query] =
  2213. {
  2214. :filters => {
  2215. 'status_id' => {:values => [''], :operator => 'c'}
  2216. },
  2217. :project_id => 1,
  2218. :sort => [['id', 'asc']]
  2219. }
  2220. get(:show, :params => {:id => 1})
  2221. assert_response :success
  2222. assert_select 'a', :text => /Previous/, :count => 0
  2223. assert_select 'a', :text => /Next/, :count => 0
  2224. end
  2225. def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
  2226. cf = IssueCustomField.
  2227. create!(
  2228. :name => 'User',
  2229. :is_for_all => true,
  2230. :tracker_ids => [1, 2, 3],
  2231. :field_format => 'user'
  2232. )
  2233. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  2234. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  2235. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  2236. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  2237. query =
  2238. IssueQuery.create!(
  2239. :name => 'test',
  2240. :visibility => IssueQuery::VISIBILITY_PUBLIC,
  2241. :user_id => 1, :filters => {},
  2242. :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']]
  2243. )
  2244. @request.session[:issue_query] = {:id => query.id, :project_id => nil}
  2245. get(:show, :params => {:id => 3})
  2246. assert_response :success
  2247. assert_select 'div.next-prev-links' do
  2248. assert_select 'a[href="/issues/2"]', :text => /Previous/
  2249. assert_select 'a[href="/issues/1"]', :text => /Next/
  2250. end
  2251. end
  2252. def test_show_should_display_prev_next_links_when_request_has_previous_and_next_issue_ids_params
  2253. get(
  2254. :show,
  2255. :params => {
  2256. :id => 1,
  2257. :prev_issue_id => 1,
  2258. :next_issue_id => 3,
  2259. :issue_position => 2,
  2260. :issue_count => 4
  2261. }
  2262. )
  2263. assert_response :success
  2264. assert_select 'div.next-prev-links' do
  2265. assert_select 'a[href="/issues/1"]', :text => /Previous/
  2266. assert_select 'a[href="/issues/3"]', :text => /Next/
  2267. assert_select 'span.position', :text => "2 of 4"
  2268. end
  2269. end
  2270. def test_show_should_display_category_field_if_categories_are_defined
  2271. Issue.update_all :category_id => nil
  2272. get(:show, :params => {:id => 1})
  2273. assert_response :success
  2274. assert_select '.attributes .category'
  2275. end
  2276. def test_show_should_not_display_category_field_if_no_categories_are_defined
  2277. Project.find(1).issue_categories.delete_all
  2278. get(:show, :params => {:id => 1})
  2279. assert_response :success
  2280. assert_select 'table.attributes .category', 0
  2281. end
  2282. def test_show_should_display_link_to_the_assignee
  2283. get(:show, :params => {:id => 2})
  2284. assert_response :success
  2285. assert_select '.assigned-to' do
  2286. assert_select 'a[href="/users/3"]'
  2287. end
  2288. end
  2289. def test_show_should_display_visible_changesets_from_other_projects
  2290. project = Project.find(2)
  2291. issue = project.issues.first
  2292. issue.changeset_ids = [102]
  2293. issue.save!
  2294. # changesets from other projects should be displayed even if repository
  2295. # is disabled on issue's project
  2296. project.disable_module! :repository
  2297. @request.session[:user_id] = 2
  2298. get(
  2299. :issue_tab,
  2300. :params => {
  2301. :id => issue.id,
  2302. :name => 'changesets'
  2303. },
  2304. :xhr => true
  2305. )
  2306. assert_select 'a[href=?]', '/projects/ecookbook/repository/10/revisions/3'
  2307. end
  2308. def test_show_should_display_watchers
  2309. @request.session[:user_id] = 2
  2310. issue = Issue.find(1)
  2311. issue.add_watcher User.find(2)
  2312. issue.add_watcher Group.find(10)
  2313. get(:show, :params => {:id => 1})
  2314. assert_select 'div#watchers ul' do
  2315. assert_select 'li.user-2' do
  2316. assert_select 'a[href="/users/2"]'
  2317. assert_select 'a[class*=delete]'
  2318. end
  2319. assert_select "li.user-10" do
  2320. assert_select 'a[href="/users/10"]', false
  2321. assert_select 'a[class*=delete]'
  2322. end
  2323. end
  2324. end
  2325. def test_show_should_display_watchers_with_gravatars
  2326. @request.session[:user_id] = 2
  2327. issue = Issue.find(1)
  2328. issue.add_watcher User.find(2)
  2329. issue.add_watcher Group.find(10)
  2330. with_settings :gravatar_enabled => '1' do
  2331. get(:show, :params => {:id => 1})
  2332. end
  2333. assert_select 'div#watchers ul' do
  2334. assert_select 'li.user-2' do
  2335. assert_select 'img.gravatar[title=?]', 'John Smith'
  2336. assert_select 'a[href="/users/2"]'
  2337. assert_select 'a[class*=delete]'
  2338. end
  2339. assert_select "li.user-10" do
  2340. assert_select 'img.gravatar[title=?]', 'A Team'
  2341. assert_select 'a[href="/users/10"]', false
  2342. assert_select 'a[class*=delete]'
  2343. end
  2344. end
  2345. end
  2346. def test_show_with_thumbnails_enabled_should_display_thumbnails
  2347. skip unless convert_installed?
  2348. @request.session[:user_id] = 2
  2349. with_settings :thumbnails_enabled => '1' do
  2350. get(:show, :params => {:id => 14})
  2351. assert_response :success
  2352. end
  2353. assert_select 'div.thumbnails' do
  2354. assert_select 'a[href="/attachments/16"]' do
  2355. assert_select 'img[src="/attachments/thumbnail/16"]'
  2356. end
  2357. end
  2358. end
  2359. def test_show_with_thumbnails_disabled_should_not_display_thumbnails
  2360. @request.session[:user_id] = 2
  2361. with_settings :thumbnails_enabled => '0' do
  2362. get(:show, :params => {:id => 14})
  2363. assert_response :success
  2364. end
  2365. assert_select 'div.thumbnails', 0
  2366. end
  2367. def test_show_with_multi_custom_field
  2368. field = CustomField.find(1)
  2369. field.update_attribute :multiple, true
  2370. issue = Issue.find(1)
  2371. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  2372. issue.save!
  2373. get(:show, :params => {:id => 1})
  2374. assert_response :success
  2375. assert_select ".cf_1 .value", :text => 'MySQL, Oracle'
  2376. end
  2377. def test_show_with_full_width_layout_custom_field_should_show_field_under_description
  2378. field =
  2379. IssueCustomField.
  2380. create!(
  2381. :name => 'Long text',
  2382. :field_format => 'text', :full_width_layout => '1',
  2383. :tracker_ids => [1], :is_for_all => true
  2384. )
  2385. issue = Issue.find(1)
  2386. issue.custom_field_values = {field.id => 'This is a long text'}
  2387. issue.save!
  2388. get(:show, :params => {:id => 1})
  2389. assert_response :success
  2390. # long text custom field should not be render in the attributes div
  2391. assert_select "div.attributes div.attribute.cf_#{field.id} p strong", 0, :text => 'Long text'
  2392. assert_select(
  2393. "div.attributes div.attribute.cf_#{field.id} div.value",
  2394. 0,
  2395. :text => 'This is a long text'
  2396. )
  2397. # long text custom field should be render under description field
  2398. assert_select "div.description ~ div.attribute.cf_#{field.id} p strong", :text => 'Long text'
  2399. assert_select(
  2400. "div.description ~ div.attribute.cf_#{field.id} div.value",
  2401. :text => 'This is a long text'
  2402. )
  2403. end
  2404. def test_show_custom_fields_with_full_text_formatting_should_be_rendered_using_wiki_class
  2405. half_field =
  2406. IssueCustomField.
  2407. create!(
  2408. :name => 'Half width field', :field_format => 'text',
  2409. :tracker_ids => [1], :is_for_all => true, :text_formatting => 'full'
  2410. )
  2411. full_field =
  2412. IssueCustomField.
  2413. create!(
  2414. :name => 'Full width field',
  2415. :field_format => 'text', :full_width_layout => '1',
  2416. :tracker_ids => [1], :is_for_all => true, :text_formatting => 'full'
  2417. )
  2418. issue = Issue.find(1)
  2419. issue.custom_field_values =
  2420. {full_field.id => 'This is a long text',
  2421. half_field.id => 'This is a short text'}
  2422. issue.save!
  2423. get(:show, :params => {:id => 1})
  2424. assert_response :success
  2425. assert_select "div.attribute.cf_#{half_field.id} div.value div.wiki", 1
  2426. assert_select "div.attribute.cf_#{full_field.id} div.value div.wiki", 1
  2427. end
  2428. def test_show_with_multi_user_custom_field
  2429. field =
  2430. IssueCustomField.
  2431. create!(
  2432. :name => 'Multi user',
  2433. :field_format => 'user', :multiple => true,
  2434. :tracker_ids => [1], :is_for_all => true
  2435. )
  2436. issue = Issue.find(1)
  2437. issue.custom_field_values = {field.id => ['2', '3']}
  2438. issue.save!
  2439. get(:show, :params => {:id => 1})
  2440. assert_response :success
  2441. assert_select ".cf_#{field.id} .value", :text => 'Dave Lopper, John Smith' do
  2442. assert_select 'a', :text => 'Dave Lopper'
  2443. assert_select 'a', :text => 'John Smith'
  2444. end
  2445. end
  2446. def test_show_should_not_display_default_value_for_new_custom_field
  2447. prior = Issue.generate!
  2448. field =
  2449. IssueCustomField.
  2450. generate!(
  2451. :name => 'WithDefault', :field_format => 'string',
  2452. :default_value => 'DEFAULT'
  2453. )
  2454. after = Issue.generate!
  2455. get :show, :params => {:id => prior.id}
  2456. assert_response :success
  2457. assert_select ".cf_#{field.id} .value", :text => ''
  2458. get :show, :params => {:id => after.id}
  2459. assert_response :success
  2460. assert_select ".cf_#{field.id} .value", :text => 'DEFAULT'
  2461. end
  2462. def test_show_should_display_private_notes_with_permission_only
  2463. journal =
  2464. Journal.
  2465. create!(
  2466. :journalized => Issue.find(2),
  2467. :notes => 'Privates notes',
  2468. :private_notes => true,
  2469. :user_id => 1
  2470. )
  2471. @request.session[:user_id] = 2
  2472. get(:show, :params => {:id => 2})
  2473. assert_response :success
  2474. assert_select "#change-#{journal.id}", 1
  2475. Role.find(1).remove_permission! :view_private_notes
  2476. get(:show, :params => {:id => 2})
  2477. assert_response :success
  2478. assert_select "#change-#{journal.id}", 0
  2479. end
  2480. def test_show_should_display_private_notes_created_by_current_user
  2481. User.find(3).roles_for_project(Project.find(1)).each do |role|
  2482. role.remove_permission! :view_private_notes
  2483. end
  2484. visible =
  2485. Journal.
  2486. create!(
  2487. :journalized => Issue.find(2),
  2488. :notes => 'Private notes',
  2489. :private_notes => true, :user_id => 3
  2490. )
  2491. not_visible =
  2492. Journal.create!(
  2493. :journalized => Issue.find(2),
  2494. :notes => 'Private notes',
  2495. :private_notes => true, :user_id => 1
  2496. )
  2497. @request.session[:user_id] = 3
  2498. get(:show, :params => {:id => 2})
  2499. assert_response :success
  2500. assert_select "#change-#{visible.id}", 1
  2501. assert_select "#change-#{not_visible.id}", 0
  2502. end
  2503. def test_show_atom
  2504. get(
  2505. :show,
  2506. :params => {
  2507. :id => 2,
  2508. :format => 'atom'
  2509. }
  2510. )
  2511. assert_response :success
  2512. assert_equal 'application/atom+xml', response.media_type
  2513. # Inline image
  2514. assert_select(
  2515. 'content',
  2516. :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
  2517. )
  2518. end
  2519. def test_show_export_to_pdf
  2520. issue = Issue.find(3)
  2521. assert issue.relations.select{|r| r.other_issue(issue).visible?}.present?
  2522. get(
  2523. :show,
  2524. :params => {
  2525. :id => 3,
  2526. :format => 'pdf'
  2527. }
  2528. )
  2529. assert_response :success
  2530. assert_equal 'application/pdf', @response.media_type
  2531. assert @response.body.starts_with?('%PDF')
  2532. end
  2533. def test_export_to_pdf_with_utf8_u_fffd
  2534. issue = Issue.generate!(:subject => "�")
  2535. ["en", "zh", "zh-TW", "ja", "ko", "ar"].each do |lang|
  2536. with_settings :default_language => lang do
  2537. get(
  2538. :show,
  2539. :params => {
  2540. :id => issue.id,
  2541. :format => 'pdf'
  2542. }
  2543. )
  2544. assert_response :success
  2545. assert_equal 'application/pdf', @response.media_type
  2546. assert @response.body.starts_with?('%PDF')
  2547. end
  2548. end
  2549. end
  2550. def test_show_export_to_pdf_with_ancestors
  2551. issue = Issue.generate!(:project_id => 1, :author_id => 2,
  2552. :tracker_id => 1, :subject => 'child',
  2553. :parent_issue_id => 1)
  2554. get(
  2555. :show,
  2556. :params => {
  2557. :id => issue.id,
  2558. :format => 'pdf'
  2559. }
  2560. )
  2561. assert_response :success
  2562. assert_equal 'application/pdf', @response.media_type
  2563. assert @response.body.starts_with?('%PDF')
  2564. end
  2565. def test_show_export_to_pdf_with_descendants
  2566. c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1,
  2567. :subject => 'child', :parent_issue_id => 1)
  2568. c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1,
  2569. :subject => 'child', :parent_issue_id => 1)
  2570. c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1,
  2571. :subject => 'child', :parent_issue_id => c1.id)
  2572. get(
  2573. :show,
  2574. :params => {
  2575. :id => 1,
  2576. :format => 'pdf'
  2577. }
  2578. )
  2579. assert_response :success
  2580. assert_equal 'application/pdf', @response.media_type
  2581. assert @response.body.starts_with?('%PDF')
  2582. end
  2583. def test_show_export_to_pdf_with_journals
  2584. get(
  2585. :show,
  2586. :params => {
  2587. :id => 1,
  2588. :format => 'pdf'
  2589. }
  2590. )
  2591. assert_response :success
  2592. assert_equal 'application/pdf', @response.media_type
  2593. assert @response.body.starts_with?('%PDF')
  2594. end
  2595. def test_show_export_to_pdf_with_private_journal
  2596. Journal.create!(
  2597. :journalized => Issue.find(1),
  2598. :notes => 'Private notes',
  2599. :private_notes => true,
  2600. :user_id => 3
  2601. )
  2602. @request.session[:user_id] = 3
  2603. get(
  2604. :show,
  2605. :params => {
  2606. :id => 1,
  2607. :format => 'pdf'
  2608. }
  2609. )
  2610. assert_response :success
  2611. assert_equal 'application/pdf', @response.media_type
  2612. assert @response.body.starts_with?('%PDF')
  2613. end
  2614. def test_show_export_to_pdf_with_changesets
  2615. [[100], [100, 101], [100, 101, 102]].each do |cs|
  2616. issue1 = Issue.find(3)
  2617. issue1.changesets = Changeset.find(cs)
  2618. issue1.save!
  2619. issue = Issue.find(3)
  2620. assert_equal issue.changesets.count, cs.size
  2621. get(
  2622. :show,
  2623. :params => {
  2624. :id => 3,
  2625. :format => 'pdf'
  2626. }
  2627. )
  2628. assert_response :success
  2629. assert_equal 'application/pdf', @response.media_type
  2630. assert @response.body.starts_with?('%PDF')
  2631. end
  2632. end
  2633. def test_show_invalid_should_respond_with_404
  2634. get(:show, :params => {:id => 999})
  2635. assert_response 404
  2636. end
  2637. def test_show_on_active_project_should_display_edit_links
  2638. @request.session[:user_id] = 1
  2639. get(:show, :params => {:id => 1})
  2640. assert_response :success
  2641. assert_select 'a', :text => 'Edit'
  2642. assert_select 'a', :text => 'Delete'
  2643. end
  2644. def test_show_on_closed_project_should_not_display_edit_links
  2645. Issue.find(1).project.close
  2646. @request.session[:user_id] = 1
  2647. get(:show, :params => {:id => 1})
  2648. assert_response :success
  2649. assert_select 'a', :text => 'Edit', :count => 0
  2650. assert_select 'a', :text => 'Delete', :count => 0
  2651. end
  2652. def test_show_should_not_display_history_tabs_for_issue_without_journals
  2653. @request.session[:user_id] = 1
  2654. get :show, :params => {:id => 5}
  2655. assert_response :success
  2656. assert_select '#history div.tabs', 0
  2657. assert_select '#history p.nodata', :text => 'No data to display'
  2658. end
  2659. def test_show_display_only_all_and_notes_tabs_for_issue_with_notes_only
  2660. @request.session[:user_id] = 1
  2661. get :show, :params => {:id => 6}
  2662. assert_response :success
  2663. assert_select '#history' do
  2664. assert_select 'div.tabs ul a', 2
  2665. assert_select 'div.tabs a[id=?]', 'tab-history', :text => 'History'
  2666. assert_select 'div.tabs a[id=?]', 'tab-notes', :text => 'Notes'
  2667. end
  2668. end
  2669. def test_show_display_only_all_and_history_tabs_for_issue_with_history_changes_only
  2670. journal = Journal.create!(:journalized => Issue.find(5), :user_id => 1)
  2671. detail =
  2672. JournalDetail.
  2673. create!(
  2674. :journal => journal, :property => 'attr',
  2675. :prop_key => 'description',
  2676. :old_value => 'Foo', :value => 'Bar'
  2677. )
  2678. @request.session[:user_id] = 1
  2679. get :show, :params => {:id => 5}
  2680. assert_response :success
  2681. assert_select '#history' do
  2682. assert_select 'div.tabs ul a', 2
  2683. assert_select 'div.tabs a[id=?]', 'tab-history', :text => 'History'
  2684. assert_select 'div.tabs a[id=?]', 'tab-properties', :text => 'Property changes'
  2685. end
  2686. end
  2687. def test_show_display_all_notes_and_history_tabs_for_issue_with_notes_and_history_changes
  2688. journal = Journal.create!(:journalized => Issue.find(6), :user_id => 1)
  2689. detail =
  2690. JournalDetail.
  2691. create!(
  2692. :journal => journal, :property => 'attr',
  2693. :prop_key => 'description',
  2694. :old_value => 'Foo', :value => 'Bar'
  2695. )
  2696. @request.session[:user_id] = 1
  2697. get :show, :params => {:id => 6}
  2698. assert_response :success
  2699. assert_select '#history' do
  2700. assert_select 'div.tabs ul a', 3
  2701. assert_select 'div.tabs a[id=?]', 'tab-history', :text => 'History'
  2702. assert_select 'div.tabs a[id=?]', 'tab-notes', :text => 'Notes'
  2703. assert_select 'div.tabs a[id=?]', 'tab-properties', :text => 'Property changes'
  2704. end
  2705. end
  2706. def test_show_display_changesets_tab_for_issue_with_changesets
  2707. project = Project.find(2)
  2708. issue = Issue.find(9)
  2709. issue.changeset_ids = [102]
  2710. issue.save!
  2711. @request.session[:user_id] = 2
  2712. get :show, :params => {:id => issue.id}
  2713. assert_select '#history' do
  2714. assert_select 'div.tabs ul a', 1
  2715. assert_select 'div.tabs a[id=?]', 'tab-changesets', :text => 'Associated revisions'
  2716. end
  2717. end
  2718. def test_show_should_display_spent_time_tab_for_issue_with_time_entries
  2719. @request.session[:user_id] = 1
  2720. get :show, :params => {:id => 3}
  2721. assert_response :success
  2722. assert_select '#history' do
  2723. assert_select 'div.tabs ul a', 1
  2724. assert_select 'div.tabs a[id=?]', 'tab-time_entries', :text => 'Spent time'
  2725. end
  2726. get(
  2727. :issue_tab,
  2728. :params => {
  2729. :id => 3,
  2730. :name => 'time_entries'
  2731. },
  2732. :xhr => true
  2733. )
  2734. assert_response :success
  2735. assert_select 'div[id=?]', 'time-entry-3' do
  2736. assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
  2737. assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
  2738. assert_select 'ul[class=?]', 'details', :text => /1.00 h/
  2739. end
  2740. end
  2741. def test_show_should_display_open_badge_for_open_issue
  2742. get :show, params: {id: 1}
  2743. assert_response :success
  2744. assert_select 'span.badge.badge-status-open', text: 'open'
  2745. end
  2746. def test_show_should_display_closed_badge_for_closed_issue
  2747. get :show, params: {id: 8}
  2748. assert_response :success
  2749. assert_select 'span.badge.badge-status-closed', text: 'closed'
  2750. end
  2751. def test_get_new
  2752. @request.session[:user_id] = 2
  2753. get(
  2754. :new,
  2755. :params => {
  2756. :project_id => 1,
  2757. :tracker_id => 1
  2758. }
  2759. )
  2760. assert_response :success
  2761. assert_select 'form#issue-form[action=?]', '/projects/ecookbook/issues'
  2762. assert_select 'form#issue-form' do
  2763. assert_select 'input[name=?]', 'issue[is_private]'
  2764. assert_select 'select[name=?]', 'issue[project_id]'
  2765. assert_select 'select[name=?]', 'issue[tracker_id]'
  2766. assert_select 'input[name=?]', 'issue[subject]'
  2767. assert_select 'textarea[name=?]', 'issue[description]'
  2768. assert_select 'select[name=?]', 'issue[status_id]'
  2769. assert_select 'select[name=?]', 'issue[priority_id]'
  2770. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  2771. assert_select 'select[name=?]', 'issue[category_id]'
  2772. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  2773. assert_select 'input[name=?]', 'issue[parent_issue_id]'
  2774. assert_select 'input[name=?]', 'issue[start_date]'
  2775. assert_select 'input[name=?]', 'issue[due_date]'
  2776. assert_select 'select[name=?]', 'issue[done_ratio]'
  2777. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
  2778. assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
  2779. end
  2780. # Be sure we don't display inactive IssuePriorities
  2781. assert ! IssuePriority.find(15).active?
  2782. assert_select 'select[name=?]', 'issue[priority_id]' do
  2783. assert_select 'option[value="15"]', 0
  2784. end
  2785. end
  2786. def test_get_new_should_show_project_selector_for_project_with_subprojects
  2787. @request.session[:user_id] = 2
  2788. get(
  2789. :new,
  2790. :params => {
  2791. :project_id => 1,
  2792. :tracker_id => 1
  2793. }
  2794. )
  2795. assert_response :success
  2796. assert_select 'select[name="issue[project_id]"]' do
  2797. assert_select 'option', 3
  2798. assert_select 'option[selected=selected]', :text => 'eCookbook'
  2799. assert_select 'option[value=?]', '5', :text => '  » Private child of eCookbook'
  2800. assert_select 'option[value=?]', '3', :text => '  » eCookbook Subproject 1'
  2801. # user_id 2 is not allowed to add issues on project_id 4 (it's not a member)
  2802. assert_select 'option[value=?]', '4', 0
  2803. end
  2804. end
  2805. def test_get_new_should_not_show_project_selector_for_project_without_subprojects
  2806. @request.session[:user_id] = 2
  2807. get(
  2808. :new,
  2809. :params => {
  2810. :project_id => 2,
  2811. :tracker_id => 1
  2812. }
  2813. )
  2814. assert_response :success
  2815. assert_select 'select[name="issue[project_id]"]', 0
  2816. end
  2817. def test_get_new_with_minimal_permissions
  2818. Role.find(1).update_attribute :permissions, [:add_issues]
  2819. WorkflowTransition.where(:role_id => 1).delete_all
  2820. @request.session[:user_id] = 2
  2821. get(
  2822. :new,
  2823. :params => {
  2824. :project_id => 1,
  2825. :tracker_id => 1
  2826. }
  2827. )
  2828. assert_response :success
  2829. assert_select 'form#issue-form' do
  2830. assert_select 'input[name=?]', 'issue[is_private]', 0
  2831. assert_select 'select[name=?]', 'issue[project_id]'
  2832. assert_select 'select[name=?]', 'issue[tracker_id]'
  2833. assert_select 'input[name=?]', 'issue[subject]'
  2834. assert_select 'textarea[name=?]', 'issue[description]'
  2835. assert_select 'select[name=?]', 'issue[status_id]'
  2836. assert_select 'select[name=?]', 'issue[priority_id]'
  2837. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  2838. assert_select 'select[name=?]', 'issue[category_id]'
  2839. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  2840. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  2841. assert_select 'input[name=?]', 'issue[start_date]'
  2842. assert_select 'input[name=?]', 'issue[due_date]'
  2843. assert_select 'select[name=?]', 'issue[done_ratio]'
  2844. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
  2845. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  2846. end
  2847. end
  2848. def test_new_without_project_id
  2849. @request.session[:user_id] = 2
  2850. get :new
  2851. assert_response :success
  2852. assert_select 'form#issue-form[action=?]', '/issues'
  2853. assert_select 'form#issue-form' do
  2854. assert_select 'select[name=?]', 'issue[project_id]'
  2855. end
  2856. end
  2857. def test_new_with_me_assigned_to_id
  2858. @request.session[:user_id] = 2
  2859. get(
  2860. :new,
  2861. :params => {
  2862. :issue => {:assigned_to_id => 'me'}
  2863. }
  2864. )
  2865. assert_response :success
  2866. assert_select 'select[name=?]', 'issue[assigned_to_id]' do
  2867. assert_select 'option[value="2"][selected=selected]'
  2868. end
  2869. end
  2870. def test_new_should_select_default_status
  2871. @request.session[:user_id] = 2
  2872. get(:new, :params => {:project_id => 1})
  2873. assert_response :success
  2874. assert_select 'select[name=?]', 'issue[status_id]' do
  2875. assert_select 'option[value="1"][selected=selected]'
  2876. end
  2877. assert_select 'input[name=was_default_status][value="1"]'
  2878. end
  2879. def test_new_should_propose_allowed_statuses
  2880. WorkflowTransition.delete_all
  2881. WorkflowTransition.create!(:tracker_id => 1, :role_id => 1,
  2882. :old_status_id => 0, :new_status_id => 1)
  2883. WorkflowTransition.create!(:tracker_id => 1, :role_id => 1,
  2884. :old_status_id => 0, :new_status_id => 3)
  2885. @request.session[:user_id] = 2
  2886. get(:new, :params => {:project_id => 1})
  2887. assert_response :success
  2888. assert_select 'select[name=?]', 'issue[status_id]' do
  2889. assert_select 'option[value="1"]'
  2890. assert_select 'option[value="3"]'
  2891. assert_select 'option', 2
  2892. assert_select 'option[value="1"][selected=selected]'
  2893. end
  2894. end
  2895. def test_new_should_propose_allowed_statuses_without_default_status_allowed
  2896. WorkflowTransition.delete_all
  2897. WorkflowTransition.create!(:tracker_id => 1, :role_id => 1,
  2898. :old_status_id => 0, :new_status_id => 2)
  2899. assert_equal 1, Tracker.find(1).default_status_id
  2900. @request.session[:user_id] = 2
  2901. get(:new, :params => {:project_id => 1})
  2902. assert_response :success
  2903. assert_select 'select[name=?]', 'issue[status_id]' do
  2904. assert_select 'option[value="2"]'
  2905. assert_select 'option', 1
  2906. assert_select 'option[value="2"][selected=selected]'
  2907. end
  2908. end
  2909. def test_new_should_propose_allowed_trackers
  2910. role = Role.find(1)
  2911. role.set_permission_trackers 'add_issues', [1, 3]
  2912. role.save!
  2913. @request.session[:user_id] = 2
  2914. get(:new, :params => {:project_id => 1})
  2915. assert_response :success
  2916. assert_select 'select[name=?]', 'issue[tracker_id]' do
  2917. assert_select 'option', 2
  2918. assert_select 'option[value="1"]'
  2919. assert_select 'option[value="3"]'
  2920. end
  2921. end
  2922. def test_new_should_default_to_first_tracker
  2923. @request.session[:user_id] = 2
  2924. get(:new, :params => {:project_id => 1})
  2925. assert_response :success
  2926. assert_select 'select[name=?]', 'issue[tracker_id]' do
  2927. assert_select 'option', 3
  2928. assert_select 'option[value="1"][selected=selected]'
  2929. end
  2930. end
  2931. def test_new_with_parent_issue_id_should_default_to_first_tracker_without_disabled_parent_field
  2932. tracker = Tracker.find(1)
  2933. tracker.core_fields -= ['parent_issue_id']
  2934. tracker.save!
  2935. @request.session[:user_id] = 2
  2936. get(
  2937. :new,
  2938. :params => {
  2939. :project_id => 1,
  2940. :issue => {
  2941. :parent_issue_id => 1
  2942. }
  2943. }
  2944. )
  2945. assert_response :success
  2946. assert_select 'select[name=?]', 'issue[tracker_id]' do
  2947. assert_select 'option', 2
  2948. assert_select 'option[value="2"][selected=selected]'
  2949. assert_select 'option[value="1"]', 0
  2950. end
  2951. end
  2952. def test_new_without_allowed_trackers_should_respond_with_403
  2953. role = Role.find(1)
  2954. role.set_permission_trackers 'add_issues', []
  2955. role.save!
  2956. @request.session[:user_id] = 2
  2957. get(:new, :params => {:project_id => 1})
  2958. assert_response 403
  2959. end
  2960. def test_new_without_projects_should_respond_with_403
  2961. Project.delete_all
  2962. @request.session[:user_id] = 2
  2963. get :new
  2964. assert_response 403
  2965. assert_select_error /no projects/
  2966. end
  2967. def test_new_without_enabled_trackers_on_projects_should_respond_with_403
  2968. Project.all.each {|p| p.trackers.clear}
  2969. @request.session[:user_id] = 2
  2970. get :new
  2971. assert_response 403
  2972. assert_select_error /no projects/
  2973. end
  2974. def test_new_should_preselect_default_version
  2975. version = Version.generate!(:project_id => 1)
  2976. Project.find(1).update_attribute :default_version_id, version.id
  2977. @request.session[:user_id] = 2
  2978. get(:new, :params => {:project_id => 1})
  2979. assert_response :success
  2980. assert_select 'select[name=?]', 'issue[fixed_version_id]' do
  2981. assert_select 'option[value=?][selected=selected]', version.id.to_s
  2982. end
  2983. end
  2984. def test_get_new_with_list_custom_field
  2985. @request.session[:user_id] = 2
  2986. get(
  2987. :new,
  2988. :params => {
  2989. :project_id => 1,
  2990. :tracker_id => 1
  2991. }
  2992. )
  2993. assert_response :success
  2994. assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
  2995. assert_select 'option', 4
  2996. assert_select 'option[value=MySQL]', :text => 'MySQL'
  2997. end
  2998. end
  2999. def test_get_new_with_multi_custom_field
  3000. field = IssueCustomField.find(1)
  3001. field.update_attribute :multiple, true
  3002. @request.session[:user_id] = 2
  3003. get(
  3004. :new,
  3005. :params => {
  3006. :project_id => 1,
  3007. :tracker_id => 1
  3008. }
  3009. )
  3010. assert_response :success
  3011. assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
  3012. assert_select 'option', 3
  3013. assert_select 'option[value=MySQL]', :text => 'MySQL'
  3014. end
  3015. assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
  3016. end
  3017. def test_get_new_with_multi_user_custom_field
  3018. field =
  3019. IssueCustomField.
  3020. create!(
  3021. :name => 'Multi user', :field_format => 'user', :multiple => true,
  3022. :tracker_ids => [1], :is_for_all => true
  3023. )
  3024. @request.session[:user_id] = 2
  3025. get(
  3026. :new,
  3027. :params => {
  3028. :project_id => 1,
  3029. :tracker_id => 1
  3030. }
  3031. )
  3032. assert_response :success
  3033. assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
  3034. assert_select 'option', Project.find(1).users.count + 1 # users + 'me'
  3035. assert_select 'option[value="2"]', :text => 'John Smith'
  3036. end
  3037. assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
  3038. end
  3039. def test_get_new_with_date_custom_field
  3040. field = IssueCustomField.create!(:name => 'Date', :field_format => 'date',
  3041. :tracker_ids => [1], :is_for_all => true)
  3042. @request.session[:user_id] = 2
  3043. get(
  3044. :new,
  3045. :params => {
  3046. :project_id => 1,
  3047. :tracker_id => 1
  3048. }
  3049. )
  3050. assert_response :success
  3051. assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
  3052. end
  3053. def test_get_new_with_text_custom_field
  3054. field = IssueCustomField.create!(:name => 'Text', :field_format => 'text',
  3055. :tracker_ids => [1], :is_for_all => true)
  3056. @request.session[:user_id] = 2
  3057. get(
  3058. :new,
  3059. :params => {
  3060. :project_id => 1,
  3061. :tracker_id => 1
  3062. }
  3063. )
  3064. assert_response :success
  3065. assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
  3066. end
  3067. def test_get_new_without_default_start_date_is_creation_date
  3068. with_settings :default_issue_start_date_to_creation_date => 0 do
  3069. @request.session[:user_id] = 2
  3070. get(
  3071. :new,
  3072. :params => {
  3073. :project_id => 1,
  3074. :tracker_id => 1
  3075. }
  3076. )
  3077. assert_response :success
  3078. assert_select 'input[name=?]', 'issue[start_date]'
  3079. assert_select 'input[name=?][value]', 'issue[start_date]', 0
  3080. end
  3081. end
  3082. def test_get_new_with_default_start_date_is_creation_date
  3083. with_settings :default_issue_start_date_to_creation_date => 1 do
  3084. @request.session[:user_id] = 2
  3085. get(
  3086. :new,
  3087. :params => {
  3088. :project_id => 1,
  3089. :tracker_id => 1
  3090. }
  3091. )
  3092. assert_response :success
  3093. assert_select 'input[name=?][value=?]', 'issue[start_date]',
  3094. Date.today.to_s
  3095. end
  3096. end
  3097. def test_get_new_form_should_allow_attachment_upload
  3098. @request.session[:user_id] = 2
  3099. get(
  3100. :new,
  3101. :params => {
  3102. :project_id => 1,
  3103. :tracker_id => 1
  3104. }
  3105. )
  3106. assert_response :success
  3107. assert_select 'form[id=issue-form][method=post][enctype="multipart/form-data"]' do
  3108. assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
  3109. end
  3110. end
  3111. def test_get_new_should_prefill_the_form_from_params
  3112. @request.session[:user_id] = 2
  3113. get(
  3114. :new,
  3115. :params => {
  3116. :project_id => 1,
  3117. :issue => {
  3118. :tracker_id => 3,
  3119. :description => 'Prefilled',
  3120. :custom_field_values => {
  3121. '2' => 'Custom field value'
  3122. }
  3123. }
  3124. }
  3125. )
  3126. assert_select 'select[name=?]', 'issue[tracker_id]' do
  3127. assert_select 'option[value="3"][selected=selected]'
  3128. end
  3129. assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
  3130. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
  3131. end
  3132. def test_get_new_should_mark_required_fields
  3133. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
  3134. :is_for_all => true, :tracker_ids => [1, 2])
  3135. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string',
  3136. :is_for_all => true, :tracker_ids => [1, 2])
  3137. WorkflowPermission.delete_all
  3138. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
  3139. :field_name => 'due_date', :rule => 'required')
  3140. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
  3141. :field_name => cf2.id.to_s, :rule => 'required')
  3142. @request.session[:user_id] = 2
  3143. get(:new, :params => {:project_id => 1})
  3144. assert_response :success
  3145. assert_select 'label[for=issue_start_date]' do
  3146. assert_select 'span[class=required]', 0
  3147. end
  3148. assert_select 'label[for=issue_due_date]' do
  3149. assert_select 'span[class=required]'
  3150. end
  3151. assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
  3152. assert_select 'span[class=required]', 0
  3153. end
  3154. assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
  3155. assert_select 'span[class=required]'
  3156. end
  3157. end
  3158. def test_get_new_should_not_display_readonly_fields
  3159. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
  3160. :is_for_all => true, :tracker_ids => [1, 2])
  3161. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string',
  3162. :is_for_all => true, :tracker_ids => [1, 2])
  3163. WorkflowPermission.delete_all
  3164. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
  3165. :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
  3166. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
  3167. :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
  3168. @request.session[:user_id] = 2
  3169. get(:new, :params => {:project_id => 1})
  3170. assert_response :success
  3171. assert_select 'input[name=?]', 'issue[start_date]'
  3172. assert_select 'input[name=?]', 'issue[due_date]', 0
  3173. assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
  3174. assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
  3175. end
  3176. def test_new_with_tracker_set_as_readonly_should_accept_status
  3177. WorkflowPermission.delete_all
  3178. [1, 2].each do |status_id|
  3179. WorkflowPermission.
  3180. create!(
  3181. :tracker_id => 1,
  3182. :old_status_id => status_id,
  3183. :role_id => 1,
  3184. :field_name => 'tracker_id',
  3185. :rule => 'readonly'
  3186. )
  3187. end
  3188. @request.session[:user_id] = 2
  3189. get(
  3190. :new,
  3191. :params => {
  3192. :project_id => 1,
  3193. :issue => {
  3194. :status_id => 2
  3195. }
  3196. }
  3197. )
  3198. assert_select 'select[name=?]', 'issue[tracker_id]', 0
  3199. assert_select 'select[name=?]', 'issue[status_id]' do
  3200. assert_select 'option[value=?][selected=selected]', '2'
  3201. end
  3202. end
  3203. def test_get_new_without_tracker_id
  3204. @request.session[:user_id] = 2
  3205. get(
  3206. :new,
  3207. :params => {
  3208. :project_id => 1
  3209. }
  3210. )
  3211. assert_response :success
  3212. assert_select 'select[name=?]', 'issue[tracker_id]' do
  3213. assert_select 'option[value=?][selected=selected]', Project.find(1).trackers.first.id.to_s
  3214. end
  3215. end
  3216. def test_get_new_with_no_default_status_should_display_an_error
  3217. @request.session[:user_id] = 2
  3218. IssueStatus.delete_all
  3219. get(
  3220. :new,
  3221. :params => {
  3222. :project_id => 1
  3223. }
  3224. )
  3225. assert_response 500
  3226. assert_select_error /No default issue/
  3227. end
  3228. def test_get_new_with_no_tracker_should_display_an_error
  3229. @request.session[:user_id] = 2
  3230. Tracker.delete_all
  3231. get(
  3232. :new,
  3233. :params => {
  3234. :project_id => 1
  3235. }
  3236. )
  3237. assert_response 500
  3238. assert_select_error /No tracker/
  3239. end
  3240. def test_new_with_invalid_project_id
  3241. @request.session[:user_id] = 1
  3242. get(
  3243. :new,
  3244. :params => {
  3245. :project_id => 'invalid'
  3246. }
  3247. )
  3248. assert_response 404
  3249. end
  3250. def test_new_with_parent_id_should_only_propose_valid_trackers
  3251. @request.session[:user_id] = 2
  3252. t = Tracker.find(3)
  3253. assert !t.disabled_core_fields.include?('parent_issue_id')
  3254. get(
  3255. :new,
  3256. :params => {
  3257. :project_id => 1, :issue => {:parent_issue_id => 1}
  3258. }
  3259. )
  3260. assert_response :success
  3261. assert_select 'option', text: /#{t.name}/, count: 1
  3262. t.core_fields = Tracker::CORE_FIELDS - ['parent_issue_id']
  3263. t.save!
  3264. assert t.disabled_core_fields.include?('parent_issue_id')
  3265. get(
  3266. :new,
  3267. :params => {
  3268. :project_id => 1, :issue => {:parent_issue_id => 1}
  3269. }
  3270. )
  3271. assert_response :success
  3272. assert_select 'option', text: /#{t.name}/, count: 0
  3273. end
  3274. def test_get_new_should_show_trackers_description
  3275. @request.session[:user_id] = 2
  3276. get :new, :params => {
  3277. :project_id => 1,
  3278. :issue => {
  3279. :tracker_id => 1
  3280. }
  3281. }
  3282. assert_response :success
  3283. assert_select 'form#issue-form' do
  3284. assert_select 'a[title=?]', 'View all trackers description', :text => 'View all trackers description'
  3285. assert_select 'select[name=?][title=?]', 'issue[tracker_id]', 'Description for Bug tracker'
  3286. end
  3287. assert_select 'div#trackers_description' do
  3288. assert_select 'h3', 1, :text => 'Trackers description'
  3289. # only Bug and Feature have descriptions
  3290. assert_select 'dt', 2, :text => 'Bug'
  3291. assert_select 'dd', 2, :text => 'Description for Bug tracker'
  3292. end
  3293. end
  3294. def test_get_new_should_not_show_trackers_description_for_trackers_without_description
  3295. Tracker.update_all(:description => '')
  3296. @request.session[:user_id] = 2
  3297. get :new, :params => {
  3298. :project_id => 1,
  3299. :issue => {
  3300. :tracker_id => 1
  3301. }
  3302. }
  3303. assert_response :success
  3304. assert_select 'form#issue-form' do
  3305. assert_select 'a[title=?]', 'View all trackers description', 0
  3306. assert_select 'select[name=?][title=?]', 'issue[tracker_id]', ''
  3307. end
  3308. assert_select 'div#trackers_description', 0
  3309. end
  3310. def test_update_form_for_new_issue
  3311. @request.session[:user_id] = 2
  3312. post(
  3313. :new,
  3314. :params => {
  3315. :project_id => 1,
  3316. :issue => {
  3317. :tracker_id => 2,
  3318. :subject => 'This is the test_new issue',
  3319. :description => 'This is the description',
  3320. :priority_id => 5
  3321. }
  3322. },
  3323. :xhr => true
  3324. )
  3325. assert_response :success
  3326. assert_equal 'text/javascript', response.media_type
  3327. assert_include 'This is the test_new issue', response.body
  3328. end
  3329. def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
  3330. @request.session[:user_id] = 2
  3331. WorkflowTransition.delete_all
  3332. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
  3333. :old_status_id => 0, :new_status_id => 2)
  3334. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
  3335. :old_status_id => 0, :new_status_id => 5)
  3336. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
  3337. :old_status_id => 5, :new_status_id => 4)
  3338. post(
  3339. :new,
  3340. :params => {
  3341. :project_id => 1,
  3342. :issue => {
  3343. :tracker_id => 1,
  3344. :status_id => 5,
  3345. :subject => 'This is an issue'
  3346. }
  3347. }
  3348. )
  3349. assert_select 'select[name=?]', 'issue[status_id]' do
  3350. assert_select 'option[value=?][selected=selected]', '5'
  3351. assert_select 'option[value=?]', '2'
  3352. assert_select 'option', :count => 2
  3353. end
  3354. end
  3355. def test_update_form_with_default_status_should_ignore_submitted_status_id_if_equals
  3356. @request.session[:user_id] = 2
  3357. tracker = Tracker.find(2)
  3358. tracker.update! :default_status_id => 2
  3359. tracker.generate_transitions! 2 => 1, :clear => true
  3360. post(
  3361. :new,
  3362. :params => {
  3363. :project_id => 1,
  3364. :issue => {
  3365. :tracker_id => 2,
  3366. :status_id => 1
  3367. },
  3368. :was_default_status => 1
  3369. }
  3370. )
  3371. assert_response :success
  3372. assert_select 'select[name=?]', 'issue[status_id]' do
  3373. assert_select 'option[value=?][selected=selected]', '2'
  3374. end
  3375. end
  3376. def test_update_form_for_new_issue_should_ignore_version_when_changing_project
  3377. version = Version.generate!(:project_id => 1)
  3378. Project.find(1).update_attribute :default_version_id, version.id
  3379. @request.session[:user_id] = 2
  3380. post(
  3381. :new,
  3382. :params => {
  3383. :issue => {
  3384. :project_id => 1,
  3385. :fixed_version_id => ''
  3386. },
  3387. :form_update_triggered_by => 'issue_project_id'
  3388. }
  3389. )
  3390. assert_response :success
  3391. assert_select 'select[name=?]', 'issue[project_id]' do
  3392. assert_select 'option[value=?][selected=selected]', '1'
  3393. end
  3394. assert_select 'select[name=?]', 'issue[fixed_version_id]' do
  3395. assert_select 'option[value=?][selected=selected]', version.id.to_s
  3396. end
  3397. end
  3398. def test_post_create
  3399. @request.session[:user_id] = 2
  3400. assert_difference 'Issue.count' do
  3401. assert_no_difference 'Journal.count' do
  3402. post(
  3403. :create,
  3404. :params => {
  3405. :project_id => 1,
  3406. :issue => {
  3407. :tracker_id => 3,
  3408. :status_id => 2,
  3409. :subject => 'This is the test_new issue',
  3410. :description => 'This is the description',
  3411. :priority_id => 5,
  3412. :start_date => '2010-11-07',
  3413. :estimated_hours => '',
  3414. :custom_field_values => {
  3415. '2' => 'Value for field 2'
  3416. }
  3417. }
  3418. }
  3419. )
  3420. end
  3421. end
  3422. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  3423. issue = Issue.find_by_subject('This is the test_new issue')
  3424. assert_not_nil issue
  3425. assert_equal 2, issue.author_id
  3426. assert_equal 3, issue.tracker_id
  3427. assert_equal 2, issue.status_id
  3428. assert_equal Date.parse('2010-11-07'), issue.start_date
  3429. assert_nil issue.estimated_hours
  3430. v = issue.custom_values.where(:custom_field_id => 2).first
  3431. assert_not_nil v
  3432. assert_equal 'Value for field 2', v.value
  3433. end
  3434. def test_post_new_with_group_assignment
  3435. group = Group.find(11)
  3436. project = Project.find(1)
  3437. project.members << Member.new(:principal => group, :roles => [Role.givable.first])
  3438. with_settings :issue_group_assignment => '1' do
  3439. @request.session[:user_id] = 2
  3440. assert_difference 'Issue.count' do
  3441. post(
  3442. :create,
  3443. :params => {
  3444. :project_id => project.id,
  3445. :issue => {
  3446. :tracker_id => 3,
  3447. :status_id => 1,
  3448. :subject => 'This is the test_new_with_group_assignment issue',
  3449. :assigned_to_id => group.id
  3450. }
  3451. }
  3452. )
  3453. end
  3454. end
  3455. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  3456. issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
  3457. assert_not_nil issue
  3458. assert_equal group, issue.assigned_to
  3459. end
  3460. def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
  3461. with_settings :default_issue_start_date_to_creation_date => 0 do
  3462. @request.session[:user_id] = 2
  3463. assert_difference 'Issue.count' do
  3464. post(
  3465. :create,
  3466. :params => {
  3467. :project_id => 1,
  3468. :issue => {
  3469. :tracker_id => 3,
  3470. :status_id => 2,
  3471. :subject => 'This is the test_new issue',
  3472. :description => 'This is the description',
  3473. :priority_id => 5,
  3474. :estimated_hours => '',
  3475. :custom_field_values => {
  3476. '2' => 'Value for field 2'
  3477. }
  3478. }
  3479. }
  3480. )
  3481. end
  3482. assert_redirected_to :controller => 'issues', :action => 'show',
  3483. :id => Issue.last.id
  3484. issue = Issue.find_by_subject('This is the test_new issue')
  3485. assert_not_nil issue
  3486. assert_nil issue.start_date
  3487. end
  3488. end
  3489. def test_post_create_without_start_date_and_default_start_date_is_creation_date
  3490. with_settings :default_issue_start_date_to_creation_date => 1 do
  3491. @request.session[:user_id] = 2
  3492. assert_difference 'Issue.count' do
  3493. post(
  3494. :create,
  3495. :params => {
  3496. :project_id => 1,
  3497. :issue => {
  3498. :tracker_id => 3,
  3499. :status_id => 2,
  3500. :subject => 'This is the test_new issue',
  3501. :description => 'This is the description',
  3502. :priority_id => 5,
  3503. :estimated_hours => '',
  3504. :custom_field_values => {
  3505. '2' => 'Value for field 2'
  3506. }
  3507. }
  3508. }
  3509. )
  3510. end
  3511. assert_redirected_to :controller => 'issues', :action => 'show',
  3512. :id => Issue.last.id
  3513. issue = Issue.find_by_subject('This is the test_new issue')
  3514. assert_not_nil issue
  3515. assert_equal Date.today, issue.start_date
  3516. end
  3517. end
  3518. def test_post_create_and_continue
  3519. @request.session[:user_id] = 2
  3520. assert_difference 'Issue.count' do
  3521. post(
  3522. :create,
  3523. :params => {
  3524. :project_id => 1,
  3525. :issue => {
  3526. :tracker_id => 3,
  3527. :subject => 'This is first issue',
  3528. :priority_id => 5
  3529. },
  3530. :continue => ''
  3531. }
  3532. )
  3533. end
  3534. issue = Issue.order('id DESC').first
  3535. assert_redirected_to :controller => 'issues',
  3536. :action => 'new', :project_id => 'ecookbook',
  3537. :issue => {:tracker_id => 3}
  3538. assert_not_nil flash[:notice], "flash was not set"
  3539. assert_select_in flash[:notice],
  3540. 'a[href=?][title=?]', "/issues/#{issue.id}",
  3541. "This is first issue", :text => "##{issue.id}"
  3542. end
  3543. def test_post_create_without_custom_fields_param
  3544. @request.session[:user_id] = 2
  3545. assert_difference 'Issue.count' do
  3546. post(
  3547. :create,
  3548. :params => {
  3549. :project_id => 1,
  3550. :issue => {
  3551. :tracker_id => 1,
  3552. :subject => 'This is the test_new issue',
  3553. :description => 'This is the description',
  3554. :priority_id => 5
  3555. }
  3556. }
  3557. )
  3558. end
  3559. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  3560. end
  3561. def test_post_create_with_multi_custom_field
  3562. field = IssueCustomField.find_by_name('Database')
  3563. field.update_attribute(:multiple, true)
  3564. @request.session[:user_id] = 2
  3565. assert_difference 'Issue.count' do
  3566. post(
  3567. :create,
  3568. :params => {
  3569. :project_id => 1,
  3570. :issue => {
  3571. :tracker_id => 1,
  3572. :subject => 'This is the test_new issue',
  3573. :description => 'This is the description',
  3574. :priority_id => 5,
  3575. :custom_field_values => {
  3576. '1' => ['', 'MySQL', 'Oracle']
  3577. }
  3578. }
  3579. }
  3580. )
  3581. end
  3582. assert_response 302
  3583. issue = Issue.order('id DESC').first
  3584. assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
  3585. end
  3586. def test_post_create_with_empty_multi_custom_field
  3587. field = IssueCustomField.find_by_name('Database')
  3588. field.update_attribute(:multiple, true)
  3589. @request.session[:user_id] = 2
  3590. assert_difference 'Issue.count' do
  3591. post(
  3592. :create,
  3593. :params => {
  3594. :project_id => 1,
  3595. :issue => {
  3596. :tracker_id => 1,
  3597. :subject => 'This is the test_new issue',
  3598. :description => 'This is the description',
  3599. :priority_id => 5,
  3600. :custom_field_values => {
  3601. '1' => ['']
  3602. }
  3603. }
  3604. }
  3605. )
  3606. end
  3607. assert_response 302
  3608. issue = Issue.order('id DESC').first
  3609. assert_equal [''], issue.custom_field_value(1).sort
  3610. end
  3611. def test_post_create_with_multi_user_custom_field
  3612. field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
  3613. :tracker_ids => [1], :is_for_all => true)
  3614. @request.session[:user_id] = 2
  3615. assert_difference 'Issue.count' do
  3616. post(
  3617. :create,
  3618. :params => {
  3619. :project_id => 1,
  3620. :issue => {
  3621. :tracker_id => 1,
  3622. :subject => 'This is the test_new issue',
  3623. :description => 'This is the description',
  3624. :priority_id => 5,
  3625. :custom_field_values => {
  3626. field.id.to_s => ['', '2', '3']
  3627. }
  3628. }
  3629. }
  3630. )
  3631. end
  3632. assert_response 302
  3633. issue = Issue.order('id DESC').first
  3634. assert_equal ['2', '3'], issue.custom_field_value(field).sort
  3635. end
  3636. def test_post_create_with_required_custom_field_and_without_custom_fields_param
  3637. field = IssueCustomField.find_by_name('Database')
  3638. field.update_attribute(:is_required, true)
  3639. @request.session[:user_id] = 2
  3640. assert_no_difference 'Issue.count' do
  3641. post(
  3642. :create,
  3643. :params => {
  3644. :project_id => 1,
  3645. :issue => {
  3646. :tracker_id => 1,
  3647. :subject => 'This is the test_new issue',
  3648. :description => 'This is the description',
  3649. :priority_id => 5
  3650. }
  3651. }
  3652. )
  3653. end
  3654. assert_response :success
  3655. assert_select_error /Database cannot be blank/
  3656. end
  3657. def test_create_should_validate_required_fields
  3658. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  3659. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  3660. WorkflowPermission.delete_all
  3661. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
  3662. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
  3663. @request.session[:user_id] = 2
  3664. assert_no_difference 'Issue.count' do
  3665. post(
  3666. :create,
  3667. :params => {
  3668. :project_id => 1,
  3669. :issue => {
  3670. :tracker_id => 2,
  3671. :status_id => 1,
  3672. :subject => 'Test',
  3673. :start_date => '',
  3674. :due_date => '',
  3675. :custom_field_values => {
  3676. cf1.id.to_s => '', cf2.id.to_s => ''
  3677. }
  3678. }
  3679. }
  3680. )
  3681. assert_response :success
  3682. end
  3683. assert_select_error /Due date cannot be blank/i
  3684. assert_select_error /Bar cannot be blank/i
  3685. end
  3686. def test_create_should_validate_required_list_fields
  3687. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => false, :possible_values => ['a', 'b'])
  3688. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'list', :is_for_all => true, :tracker_ids => [1, 2], :multiple => true, :possible_values => ['a', 'b'])
  3689. WorkflowPermission.delete_all
  3690. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf1.id.to_s, :rule => 'required')
  3691. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
  3692. @request.session[:user_id] = 2
  3693. assert_no_difference 'Issue.count' do
  3694. post(
  3695. :create,
  3696. :params => {
  3697. :project_id => 1,
  3698. :issue => {
  3699. :tracker_id => 2,
  3700. :status_id => 1,
  3701. :subject => 'Test',
  3702. :start_date => '',
  3703. :due_date => '',
  3704. :custom_field_values => {
  3705. cf1.id.to_s => '', cf2.id.to_s => ['']
  3706. }
  3707. }
  3708. }
  3709. )
  3710. assert_response :success
  3711. end
  3712. assert_select_error /Foo cannot be blank/i
  3713. assert_select_error /Bar cannot be blank/i
  3714. end
  3715. def test_create_should_ignore_readonly_fields
  3716. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  3717. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  3718. WorkflowPermission.delete_all
  3719. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
  3720. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
  3721. @request.session[:user_id] = 2
  3722. assert_difference 'Issue.count' do
  3723. post(
  3724. :create,
  3725. :params => {
  3726. :project_id => 1,
  3727. :issue => {
  3728. :tracker_id => 2,
  3729. :status_id => 1,
  3730. :subject => 'Test',
  3731. :start_date => '2012-07-14',
  3732. :due_date => '2012-07-16',
  3733. :custom_field_values => {
  3734. cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
  3735. }
  3736. }
  3737. }
  3738. )
  3739. assert_response 302
  3740. end
  3741. issue = Issue.order('id DESC').first
  3742. assert_equal Date.parse('2012-07-14'), issue.start_date
  3743. assert_nil issue.due_date
  3744. assert_equal 'value1', issue.custom_field_value(cf1)
  3745. assert_nil issue.custom_field_value(cf2)
  3746. end
  3747. def test_create_should_ignore_unallowed_trackers
  3748. role = Role.find(1)
  3749. role.set_permission_trackers :add_issues, [3]
  3750. role.save!
  3751. @request.session[:user_id] = 2
  3752. issue = new_record(Issue) do
  3753. post(
  3754. :create,
  3755. :params => {
  3756. :project_id => 1,
  3757. :issue => {
  3758. :tracker_id => 1,
  3759. :status_id => 1,
  3760. :subject => 'Test'
  3761. }
  3762. }
  3763. )
  3764. assert_response 302
  3765. end
  3766. assert_equal 3, issue.tracker_id
  3767. end
  3768. def test_post_create_with_watchers
  3769. @request.session[:user_id] = 2
  3770. ActionMailer::Base.deliveries.clear
  3771. with_settings :notified_events => %w(issue_added) do
  3772. assert_difference 'Watcher.count', 3 do
  3773. post(
  3774. :create,
  3775. :params => {
  3776. :project_id => 1,
  3777. :issue => {
  3778. :tracker_id => 1,
  3779. :subject => 'This is a new issue with watchers',
  3780. :description => 'This is the description',
  3781. :priority_id => 5,
  3782. :watcher_user_ids => ['2', '3', '10']
  3783. }
  3784. }
  3785. )
  3786. end
  3787. end
  3788. issue = Issue.find_by_subject('This is a new issue with watchers')
  3789. assert_not_nil issue
  3790. assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
  3791. # Watchers added
  3792. assert_equal [2, 3, 10], issue.watcher_user_ids.sort
  3793. assert issue.watched_by?(User.find(3))
  3794. assert issue.watched_by?(Group.find(10))
  3795. # Watchers notified
  3796. assert_equal 3, ActionMailer::Base.deliveries.size
  3797. mail = ActionMailer::Base.deliveries[1]
  3798. assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
  3799. mail = ActionMailer::Base.deliveries[2]
  3800. assert [mail.bcc, mail.cc].flatten.include?(User.find(8).mail)
  3801. end
  3802. def test_post_create_subissue
  3803. @request.session[:user_id] = 2
  3804. assert_difference 'Issue.count' do
  3805. post(
  3806. :create,
  3807. :params => {
  3808. :project_id => 1,
  3809. :issue => {
  3810. :tracker_id => 1,
  3811. :subject => 'This is a child issue',
  3812. :parent_issue_id => '2'
  3813. }
  3814. }
  3815. )
  3816. assert_response 302
  3817. end
  3818. issue = Issue.order('id DESC').first
  3819. assert_equal Issue.find(2), issue.parent
  3820. end
  3821. def test_post_create_subissue_with_sharp_parent_id
  3822. @request.session[:user_id] = 2
  3823. assert_difference 'Issue.count' do
  3824. post(
  3825. :create,
  3826. :params => {
  3827. :project_id => 1,
  3828. :issue => {
  3829. :tracker_id => 1,
  3830. :subject => 'This is a child issue',
  3831. :parent_issue_id => '#2'
  3832. }
  3833. }
  3834. )
  3835. assert_response 302
  3836. end
  3837. issue = Issue.order('id DESC').first
  3838. assert_equal Issue.find(2), issue.parent
  3839. end
  3840. def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
  3841. @request.session[:user_id] = 2
  3842. assert_no_difference 'Issue.count' do
  3843. post(
  3844. :create,
  3845. :params => {
  3846. :project_id => 1,
  3847. :issue => {
  3848. :tracker_id => 1,
  3849. :subject => 'This is a child issue',
  3850. :parent_issue_id => '4'
  3851. }
  3852. }
  3853. )
  3854. assert_response :success
  3855. assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
  3856. assert_select_error /Parent task is invalid/i
  3857. end
  3858. end
  3859. def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
  3860. @request.session[:user_id] = 2
  3861. assert_no_difference 'Issue.count' do
  3862. post(
  3863. :create,
  3864. :params => {
  3865. :project_id => 1,
  3866. :issue => {
  3867. :tracker_id => 1,
  3868. :subject => 'This is a child issue',
  3869. :parent_issue_id => '01ABC'
  3870. }
  3871. }
  3872. )
  3873. assert_response :success
  3874. assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
  3875. assert_select_error /Parent task is invalid/i
  3876. end
  3877. end
  3878. def test_post_create_private
  3879. @request.session[:user_id] = 2
  3880. assert_difference 'Issue.count' do
  3881. post(
  3882. :create,
  3883. :params => {
  3884. :project_id => 1,
  3885. :issue => {
  3886. :tracker_id => 1,
  3887. :subject => 'This is a private issue',
  3888. :is_private => '1'
  3889. }
  3890. }
  3891. )
  3892. end
  3893. issue = Issue.order('id DESC').first
  3894. assert issue.is_private?
  3895. end
  3896. def test_post_create_private_with_set_own_issues_private_permission
  3897. role = Role.find(1)
  3898. role.remove_permission! :set_issues_private
  3899. role.add_permission! :set_own_issues_private
  3900. @request.session[:user_id] = 2
  3901. assert_difference 'Issue.count' do
  3902. post(
  3903. :create,
  3904. :params => {
  3905. :project_id => 1,
  3906. :issue => {
  3907. :tracker_id => 1,
  3908. :subject => 'This is a private issue',
  3909. :is_private => '1'
  3910. }
  3911. }
  3912. )
  3913. end
  3914. issue = Issue.order('id DESC').first
  3915. assert issue.is_private?
  3916. end
  3917. def test_create_without_project_id
  3918. @request.session[:user_id] = 2
  3919. assert_difference 'Issue.count' do
  3920. post(
  3921. :create,
  3922. :params => {
  3923. :issue => {
  3924. :project_id => 3,
  3925. :tracker_id => 2,
  3926. :subject => 'Foo'
  3927. }
  3928. }
  3929. )
  3930. assert_response 302
  3931. end
  3932. issue = Issue.order('id DESC').first
  3933. assert_equal 3, issue.project_id
  3934. assert_equal 2, issue.tracker_id
  3935. end
  3936. def test_create_without_project_id_and_continue_should_redirect_without_project_id
  3937. @request.session[:user_id] = 2
  3938. assert_difference 'Issue.count' do
  3939. post(
  3940. :create,
  3941. :params => {
  3942. :issue => {
  3943. :project_id => 3,
  3944. :tracker_id => 2,
  3945. :subject => 'Foo'
  3946. },
  3947. :continue => '1'
  3948. }
  3949. )
  3950. assert_redirected_to '/issues/new?issue%5Bproject_id%5D=3&issue%5Btracker_id%5D=2'
  3951. end
  3952. end
  3953. def test_create_without_project_id_should_be_denied_without_permission
  3954. Role.non_member.remove_permission! :add_issues
  3955. Role.anonymous.remove_permission! :add_issues
  3956. @request.session[:user_id] = 2
  3957. assert_no_difference 'Issue.count' do
  3958. post(
  3959. :create,
  3960. :params => {
  3961. :issue => {
  3962. :project_id => 3,
  3963. :tracker_id => 2,
  3964. :subject => 'Foo'
  3965. }
  3966. }
  3967. )
  3968. assert_response 422
  3969. end
  3970. end
  3971. def test_create_without_project_id_with_failure_should_not_set_project
  3972. @request.session[:user_id] = 2
  3973. post(
  3974. :create,
  3975. :params => {
  3976. :issue => {
  3977. :project_id => 3,
  3978. :tracker_id => 2,
  3979. :subject => ''
  3980. }
  3981. }
  3982. )
  3983. assert_response :success
  3984. # no project menu
  3985. assert_select '#main-menu a.overview', 0
  3986. end
  3987. def test_post_create_should_send_a_notification
  3988. ActionMailer::Base.deliveries.clear
  3989. @request.session[:user_id] = 2
  3990. with_settings :notified_events => %w(issue_added) do
  3991. assert_difference 'Issue.count' do
  3992. post(
  3993. :create,
  3994. :params => {
  3995. :project_id => 1,
  3996. :issue => {
  3997. :tracker_id => 3,
  3998. :subject => 'This is the test_new issue',
  3999. :description => 'This is the description',
  4000. :priority_id => 5,
  4001. :estimated_hours => '',
  4002. :custom_field_values => {
  4003. '2' => 'Value for field 2'
  4004. }
  4005. }
  4006. }
  4007. )
  4008. end
  4009. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  4010. assert_equal 2, ActionMailer::Base.deliveries.size
  4011. end
  4012. end
  4013. def test_post_create_should_preserve_fields_values_on_validation_failure
  4014. @request.session[:user_id] = 2
  4015. post(
  4016. :create,
  4017. :params => {
  4018. :project_id => 1,
  4019. :issue => {
  4020. :tracker_id => 1,
  4021. :subject => '', # empty subject
  4022. :description => 'This is a description',
  4023. :priority_id => 6,
  4024. :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}
  4025. }
  4026. }
  4027. )
  4028. assert_response :success
  4029. assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
  4030. assert_select 'select[name=?]', 'issue[priority_id]' do
  4031. assert_select 'option[value="6"][selected=selected]', :text => 'High'
  4032. end
  4033. # Custom fields
  4034. assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
  4035. assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
  4036. end
  4037. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
  4038. end
  4039. def test_post_create_with_failure_should_preserve_watchers
  4040. assert !User.find(8).member_of?(Project.find(1))
  4041. @request.session[:user_id] = 2
  4042. post(
  4043. :create,
  4044. :params => {
  4045. :project_id => 1,
  4046. :issue => {
  4047. :tracker_id => 1,
  4048. :watcher_user_ids => ['3', '8']
  4049. }
  4050. }
  4051. )
  4052. assert_response :success
  4053. assert_select 'input[name=?][value="2"]:not(checked)', 'issue[watcher_user_ids][]'
  4054. assert_select 'input[name=?][value="3"][checked=checked]', 'issue[watcher_user_ids][]'
  4055. assert_select 'input[name=?][value="8"][checked=checked]', 'issue[watcher_user_ids][]'
  4056. end
  4057. def test_post_create_should_ignore_non_safe_attributes
  4058. @request.session[:user_id] = 2
  4059. assert_nothing_raised do
  4060. post(
  4061. :create,
  4062. :params => {
  4063. :project_id => 1,
  4064. :issue => {
  4065. :tracker => "A param can not be a Tracker"
  4066. }
  4067. }
  4068. )
  4069. end
  4070. end
  4071. def test_post_create_with_attachment
  4072. set_tmp_attachments_directory
  4073. @request.session[:user_id] = 2
  4074. assert_difference 'Issue.count' do
  4075. assert_difference 'Attachment.count' do
  4076. assert_no_difference 'Journal.count' do
  4077. post(
  4078. :create,
  4079. :params => {
  4080. :project_id => 1,
  4081. :issue => {
  4082. :tracker_id => '1',
  4083. :subject => 'With attachment'
  4084. },
  4085. :attachments => {
  4086. '1' => {
  4087. 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
  4088. 'description' => 'test file'
  4089. }
  4090. }
  4091. }
  4092. )
  4093. end
  4094. end
  4095. end
  4096. issue = Issue.order('id DESC').first
  4097. attachment = Attachment.order('id DESC').first
  4098. assert_equal issue, attachment.container
  4099. assert_equal 2, attachment.author_id
  4100. assert_equal 'testfile.txt', attachment.filename
  4101. assert_equal 'text/plain', attachment.content_type
  4102. assert_equal 'test file', attachment.description
  4103. assert_equal 59, attachment.filesize
  4104. assert File.exists?(attachment.diskfile)
  4105. assert_equal 59, File.size(attachment.diskfile)
  4106. end
  4107. def test_post_create_with_attachment_should_notify_with_attachments
  4108. ActionMailer::Base.deliveries.clear
  4109. set_tmp_attachments_directory
  4110. @request.session[:user_id] = 2
  4111. with_settings :notified_events => %w(issue_added) do
  4112. assert_difference 'Issue.count' do
  4113. post(
  4114. :create,
  4115. :params => {
  4116. :project_id => 1,
  4117. :issue => {
  4118. :tracker_id => '1',
  4119. :subject => 'With attachment'
  4120. },
  4121. :attachments => {
  4122. '1' => {
  4123. 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
  4124. 'description' => 'test file'
  4125. }
  4126. }
  4127. }
  4128. )
  4129. end
  4130. end
  4131. assert_not_nil ActionMailer::Base.deliveries.last
  4132. assert_select_email do
  4133. assert_select 'a[href^=?]', 'http://localhost:3000/attachments/download', 'testfile.txt'
  4134. end
  4135. end
  4136. def test_post_create_with_failure_should_save_attachments
  4137. set_tmp_attachments_directory
  4138. @request.session[:user_id] = 2
  4139. assert_no_difference 'Issue.count' do
  4140. assert_difference 'Attachment.count' do
  4141. post(
  4142. :create,
  4143. :params => {
  4144. :project_id => 1,
  4145. :issue => {
  4146. :tracker_id => '1',
  4147. :subject => ''
  4148. },
  4149. :attachments => {
  4150. '1' => {
  4151. 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
  4152. 'description' => 'test file'
  4153. }
  4154. }
  4155. }
  4156. )
  4157. assert_response :success
  4158. end
  4159. end
  4160. attachment = Attachment.order('id DESC').first
  4161. assert_equal 'testfile.txt', attachment.filename
  4162. assert File.exists?(attachment.diskfile)
  4163. assert_nil attachment.container
  4164. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  4165. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  4166. end
  4167. def test_post_create_with_failure_should_keep_saved_attachments
  4168. set_tmp_attachments_directory
  4169. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  4170. @request.session[:user_id] = 2
  4171. assert_no_difference 'Issue.count' do
  4172. assert_no_difference 'Attachment.count' do
  4173. post(
  4174. :create,
  4175. :params => {
  4176. :project_id => 1,
  4177. :issue => {
  4178. :tracker_id => '1',
  4179. :subject => ''
  4180. },
  4181. :attachments => {
  4182. 'p0' => {
  4183. 'token' => attachment.token
  4184. }
  4185. }
  4186. }
  4187. )
  4188. assert_response :success
  4189. end
  4190. end
  4191. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  4192. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  4193. end
  4194. def test_post_create_should_attach_saved_attachments
  4195. set_tmp_attachments_directory
  4196. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  4197. @request.session[:user_id] = 2
  4198. assert_difference 'Issue.count' do
  4199. assert_no_difference 'Attachment.count' do
  4200. post(
  4201. :create,
  4202. :params => {
  4203. :project_id => 1,
  4204. :issue => {
  4205. :tracker_id => '1',
  4206. :subject => 'Saved attachments'
  4207. },
  4208. :attachments => {
  4209. 'p0' => {
  4210. 'token' => attachment.token
  4211. }
  4212. }
  4213. }
  4214. )
  4215. assert_response 302
  4216. end
  4217. end
  4218. issue = Issue.order('id DESC').first
  4219. assert_equal 1, issue.attachments.count
  4220. attachment.reload
  4221. assert_equal issue, attachment.container
  4222. end
  4223. def setup_without_workflow_privilege
  4224. WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
  4225. Role.anonymous.add_permission! :add_issues, :add_issue_notes
  4226. end
  4227. private :setup_without_workflow_privilege
  4228. test "without workflow privilege #new should propose default status only" do
  4229. setup_without_workflow_privilege
  4230. get(:new, :params => {:project_id => 1})
  4231. assert_response :success
  4232. assert_select 'select[name=?]', 'issue[status_id]' do
  4233. assert_select 'option', 1
  4234. assert_select 'option[value=?][selected=selected]', '1'
  4235. end
  4236. end
  4237. test "without workflow privilege #create should accept default status" do
  4238. setup_without_workflow_privilege
  4239. assert_difference 'Issue.count' do
  4240. post(
  4241. :create,
  4242. :params => {
  4243. :project_id => 1,
  4244. :issue => {
  4245. :tracker_id => 1,
  4246. :subject => 'This is an issue',
  4247. :status_id => 1
  4248. }
  4249. }
  4250. )
  4251. end
  4252. issue = Issue.order('id').last
  4253. assert_not_nil issue.default_status
  4254. assert_equal issue.default_status, issue.status
  4255. end
  4256. test "without workflow privilege #create should ignore unauthorized status" do
  4257. setup_without_workflow_privilege
  4258. assert_difference 'Issue.count' do
  4259. post(
  4260. :create,
  4261. :params => {
  4262. :project_id => 1,
  4263. :issue => {
  4264. :tracker_id => 1,
  4265. :subject => 'This is an issue',
  4266. :status_id => 3
  4267. }
  4268. }
  4269. )
  4270. end
  4271. issue = Issue.order('id').last
  4272. assert_not_nil issue.default_status
  4273. assert_equal issue.default_status, issue.status
  4274. end
  4275. test "without workflow privilege #update should ignore status change" do
  4276. setup_without_workflow_privilege
  4277. assert_difference 'Journal.count' do
  4278. put(
  4279. :update,
  4280. :params => {
  4281. :id => 1,
  4282. :issue => {
  4283. :status_id => 3,
  4284. :notes => 'just trying'
  4285. }
  4286. }
  4287. )
  4288. end
  4289. assert_equal 1, Issue.find(1).status_id
  4290. end
  4291. test "without workflow privilege #update ignore attributes changes" do
  4292. setup_without_workflow_privilege
  4293. assert_difference 'Journal.count' do
  4294. put(
  4295. :update,
  4296. :params => {
  4297. :id => 1,
  4298. :issue => {
  4299. :subject => 'changed',
  4300. :assigned_to_id => 2,
  4301. :notes => 'just trying'
  4302. }
  4303. }
  4304. )
  4305. end
  4306. issue = Issue.find(1)
  4307. assert_equal "Cannot print recipes", issue.subject
  4308. assert_nil issue.assigned_to
  4309. end
  4310. def setup_with_workflow_privilege
  4311. WorkflowTransition.where(["role_id = ?", Role.anonymous.id]).delete_all
  4312. WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
  4313. :old_status_id => 1, :new_status_id => 3)
  4314. WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1,
  4315. :old_status_id => 1, :new_status_id => 4)
  4316. Role.anonymous.add_permission! :add_issues, :add_issue_notes
  4317. end
  4318. private :setup_with_workflow_privilege
  4319. def setup_with_workflow_privilege_and_edit_issues_permission
  4320. setup_with_workflow_privilege
  4321. Role.anonymous.add_permission! :add_issues, :edit_issues
  4322. end
  4323. private :setup_with_workflow_privilege_and_edit_issues_permission
  4324. test "with workflow privilege and :edit_issues permission should accept authorized status" do
  4325. setup_with_workflow_privilege_and_edit_issues_permission
  4326. assert_difference 'Journal.count' do
  4327. put(
  4328. :update,
  4329. :params => {
  4330. :id => 1,
  4331. :issue => {
  4332. :status_id => 3,
  4333. :notes => 'just trying'
  4334. }
  4335. }
  4336. )
  4337. end
  4338. assert_equal 3, Issue.find(1).status_id
  4339. end
  4340. test "with workflow privilege and :edit_issues permission should ignore unauthorized status" do
  4341. setup_with_workflow_privilege_and_edit_issues_permission
  4342. assert_difference 'Journal.count' do
  4343. put(
  4344. :update,
  4345. :params => {
  4346. :id => 1,
  4347. :issue => {
  4348. :status_id => 2,
  4349. :notes => 'just trying'
  4350. }
  4351. }
  4352. )
  4353. end
  4354. assert_equal 1, Issue.find(1).status_id
  4355. end
  4356. test "with workflow privilege and :edit_issues permission should accept authorized attributes changes" do
  4357. setup_with_workflow_privilege_and_edit_issues_permission
  4358. assert_difference 'Journal.count' do
  4359. put(
  4360. :update,
  4361. :params => {
  4362. :id => 1,
  4363. :issue => {
  4364. :subject => 'changed',
  4365. :assigned_to_id => 2,
  4366. :notes => 'just trying'
  4367. }
  4368. }
  4369. )
  4370. end
  4371. issue = Issue.find(1)
  4372. assert_equal "changed", issue.subject
  4373. assert_equal 2, issue.assigned_to_id
  4374. end
  4375. def test_new_as_copy
  4376. orig = Issue.find(1)
  4377. @request.session[:user_id] = 2
  4378. get(
  4379. :new,
  4380. :params => {
  4381. :project_id => 1,
  4382. :copy_from => orig.id
  4383. }
  4384. )
  4385. assert_response :success
  4386. assert_select 'form[id=issue-form][action="/projects/ecookbook/issues"]' do
  4387. assert_select 'select[name=?]', 'issue[project_id]' do
  4388. assert_select 'option[value="1"][selected=selected]', :text => 'eCookbook'
  4389. assert_select 'option[value="2"]:not([selected])', :text => 'OnlineStore'
  4390. end
  4391. assert_select 'input[name=?][value=?]', 'issue[subject]', orig.subject
  4392. assert_select 'input[name=copy_from][value="1"]'
  4393. end
  4394. end
  4395. def test_new_as_copy_without_add_issues_permission_should_not_propose_current_project_as_target
  4396. user = setup_user_with_copy_but_not_add_permission
  4397. @request.session[:user_id] = user.id
  4398. get(
  4399. :new,
  4400. :params => {
  4401. :project_id => 1,
  4402. :copy_from => 1
  4403. }
  4404. )
  4405. assert_response :success
  4406. assert_select 'select[name=?]', 'issue[project_id]' do
  4407. assert_select 'option[value="1"]', 0
  4408. assert_select 'option[value="2"]', :text => 'OnlineStore'
  4409. end
  4410. end
  4411. def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
  4412. @request.session[:user_id] = 2
  4413. issue = Issue.find(3)
  4414. assert issue.attachments.count > 0
  4415. get(
  4416. :new,
  4417. :params => {
  4418. :project_id => 1,
  4419. :copy_from => 3
  4420. }
  4421. )
  4422. assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value="1"]'
  4423. end
  4424. def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
  4425. @request.session[:user_id] = 2
  4426. issue = Issue.find(3)
  4427. issue.attachments.delete_all
  4428. get(
  4429. :new,
  4430. :params => {
  4431. :project_id => 1,
  4432. :copy_from => 3
  4433. }
  4434. )
  4435. assert_select 'input[name=copy_attachments]', 0
  4436. end
  4437. def test_new_as_copy_should_preserve_parent_id
  4438. @request.session[:user_id] = 2
  4439. issue = Issue.generate!(:parent_issue_id => 2)
  4440. get(
  4441. :new,
  4442. :params => {
  4443. :project_id => 1,
  4444. :copy_from => issue.id
  4445. }
  4446. )
  4447. assert_select 'input[name=?][value="2"]', 'issue[parent_issue_id]'
  4448. end
  4449. def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
  4450. @request.session[:user_id] = 2
  4451. issue = Issue.generate_with_descendants!
  4452. get(
  4453. :new,
  4454. :params => {
  4455. :project_id => 1,
  4456. :copy_from => issue.id
  4457. }
  4458. )
  4459. assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value="1"]'
  4460. end
  4461. def test_new_as_copy_should_preserve_watchers
  4462. @request.session[:user_id] = 2
  4463. issue = Issue.find(1)
  4464. user = User.generate!
  4465. Watcher.create!(:watchable => issue, :user => user)
  4466. Watcher.create!(:watchable => issue, :user => Group.find(10))
  4467. get(
  4468. :new,
  4469. :params => {
  4470. :project_id => 1,
  4471. :copy_from => 1
  4472. }
  4473. )
  4474. assert_select 'input[type=checkbox][name=?][checked=checked]', 'issue[watcher_user_ids][]', 2
  4475. assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', user.id.to_s
  4476. assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', '10'
  4477. assert_select 'input[type=hidden][name=?][value=?]', 'issue[watcher_user_ids][]', '', 1
  4478. end
  4479. def test_new_as_copy_should_not_propose_locked_watchers
  4480. @request.session[:user_id] = 2
  4481. issue = Issue.find(1)
  4482. user = User.generate!
  4483. user2 = User.generate!
  4484. Watcher.create!(:watchable => issue, :user => user)
  4485. Watcher.create!(:watchable => issue, :user => user2)
  4486. user2.status = User::STATUS_LOCKED
  4487. user2.save!
  4488. get(
  4489. :new,
  4490. :params => {
  4491. :project_id => 1,
  4492. :copy_from => 1
  4493. }
  4494. )
  4495. assert_select 'input[type=checkbox][name=?][checked=checked]', 'issue[watcher_user_ids][]', 1
  4496. assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', user.id.to_s
  4497. assert_select 'input[type=checkbox][name=?][checked=checked][value=?]', 'issue[watcher_user_ids][]', user2.id.to_s, 0
  4498. assert_select 'input[type=hidden][name=?][value=?]', 'issue[watcher_user_ids][]', '', 1
  4499. end
  4500. def test_new_as_copy_with_invalid_issue_should_respond_with_404
  4501. @request.session[:user_id] = 2
  4502. get(
  4503. :new,
  4504. :params => {
  4505. :project_id => 1,
  4506. :copy_from => 99999
  4507. }
  4508. )
  4509. assert_response 404
  4510. end
  4511. def test_create_as_copy_on_different_project
  4512. @request.session[:user_id] = 2
  4513. assert_difference 'Issue.count' do
  4514. post(
  4515. :create,
  4516. :params => {
  4517. :project_id => 1,
  4518. :copy_from => 1,
  4519. :issue => {
  4520. :project_id => '2',
  4521. :tracker_id => '3',
  4522. :status_id => '1',
  4523. :subject => 'Copy'
  4524. }
  4525. }
  4526. )
  4527. end
  4528. issue = Issue.order('id DESC').first
  4529. assert_redirected_to "/issues/#{issue.id}"
  4530. assert_equal 2, issue.project_id
  4531. assert_equal 3, issue.tracker_id
  4532. assert_equal 'Copy', issue.subject
  4533. end
  4534. def test_create_as_copy_should_allow_status_to_be_set_to_default
  4535. copied = Issue.generate! :status_id => 2
  4536. assert_equal 2, copied.reload.status_id
  4537. @request.session[:user_id] = 2
  4538. assert_difference 'Issue.count' do
  4539. post(
  4540. :create,
  4541. :params => {
  4542. :project_id => 1,
  4543. :copy_from => copied.id,
  4544. :issue => {
  4545. :project_id => '1',
  4546. :tracker_id => '1',
  4547. :status_id => '1'
  4548. },
  4549. :was_default_status => '1'
  4550. }
  4551. )
  4552. end
  4553. issue = Issue.order('id DESC').first
  4554. assert_equal 1, issue.status_id
  4555. end
  4556. def test_create_as_copy_should_fail_without_add_issue_permission_on_original_tracker
  4557. role = Role.find(2)
  4558. role.set_permission_trackers :add_issues, [1, 3]
  4559. role.save!
  4560. Role.non_member.remove_permission! :add_issues
  4561. issue = Issue.generate!(:project_id => 1, :tracker_id => 2)
  4562. @request.session[:user_id] = 3
  4563. assert_no_difference 'Issue.count' do
  4564. post(
  4565. :create,
  4566. :params => {
  4567. :project_id => 1,
  4568. :copy_from => issue.id,
  4569. :issue => {
  4570. :project_id => '1'
  4571. }
  4572. }
  4573. )
  4574. end
  4575. assert_select_error 'Tracker is invalid'
  4576. end
  4577. def test_create_as_copy_should_copy_attachments
  4578. @request.session[:user_id] = 2
  4579. issue = Issue.find(3)
  4580. count = issue.attachments.count
  4581. assert count > 0
  4582. assert_difference 'Issue.count' do
  4583. assert_difference 'Attachment.count', count do
  4584. post(
  4585. :create,
  4586. :params => {
  4587. :project_id => 1,
  4588. :copy_from => 3,
  4589. :issue => {
  4590. :project_id => '1',
  4591. :tracker_id => '3',
  4592. :status_id => '1',
  4593. :subject => 'Copy with attachments'
  4594. },
  4595. :copy_attachments => '1'
  4596. }
  4597. )
  4598. end
  4599. end
  4600. copy = Issue.order('id DESC').first
  4601. assert_equal count, copy.attachments.count
  4602. assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
  4603. end
  4604. def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
  4605. @request.session[:user_id] = 2
  4606. issue = Issue.find(3)
  4607. count = issue.attachments.count
  4608. assert count > 0
  4609. assert_difference 'Issue.count' do
  4610. assert_no_difference 'Attachment.count' do
  4611. post(
  4612. :create,
  4613. :params => {
  4614. :project_id => 1,
  4615. :copy_from => 3,
  4616. :issue => {
  4617. :project_id => '1',
  4618. :tracker_id => '3',
  4619. :status_id => '1',
  4620. :subject => 'Copy with attachments'
  4621. }
  4622. }
  4623. )
  4624. end
  4625. end
  4626. copy = Issue.order('id DESC').first
  4627. assert_equal 0, copy.attachments.count
  4628. end
  4629. def test_create_as_copy_with_attachments_should_also_add_new_files
  4630. set_tmp_attachments_directory
  4631. @request.session[:user_id] = 2
  4632. issue = Issue.find(3)
  4633. count = issue.attachments.count
  4634. assert count > 0
  4635. assert_difference 'Issue.count' do
  4636. assert_difference 'Attachment.count', count + 1 do
  4637. post(
  4638. :create,
  4639. :params => {
  4640. :project_id => 1,
  4641. :copy_from => 3,
  4642. :issue => {
  4643. :project_id => '1',
  4644. :tracker_id => '3',
  4645. :status_id => '1',
  4646. :subject => 'Copy with attachments'
  4647. },
  4648. :copy_attachments => '1',
  4649. :attachments => {
  4650. '1' => {
  4651. 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
  4652. 'description' => 'test file'
  4653. }
  4654. }
  4655. }
  4656. )
  4657. end
  4658. end
  4659. copy = Issue.order('id DESC').first
  4660. assert_equal count + 1, copy.attachments.count
  4661. end
  4662. def test_create_as_copy_should_add_relation_with_copied_issue
  4663. @request.session[:user_id] = 2
  4664. assert_difference 'Issue.count' do
  4665. assert_difference 'IssueRelation.count' do
  4666. post(
  4667. :create,
  4668. :params => {
  4669. :project_id => 1,
  4670. :copy_from => 1,
  4671. :link_copy => '1',
  4672. :issue => {
  4673. :project_id => '1',
  4674. :tracker_id => '3',
  4675. :status_id => '1',
  4676. :subject => 'Copy'
  4677. }
  4678. }
  4679. )
  4680. end
  4681. end
  4682. copy = Issue.order('id DESC').first
  4683. assert_equal 1, copy.relations.size
  4684. end
  4685. def test_create_as_copy_should_allow_not_to_add_relation_with_copied_issue
  4686. @request.session[:user_id] = 2
  4687. assert_difference 'Issue.count' do
  4688. assert_no_difference 'IssueRelation.count' do
  4689. post(
  4690. :create,
  4691. :params => {
  4692. :project_id => 1,
  4693. :copy_from => 1,
  4694. :issue => {
  4695. :subject => 'Copy'
  4696. }
  4697. }
  4698. )
  4699. end
  4700. end
  4701. end
  4702. def test_create_as_copy_should_always_add_relation_with_copied_issue_by_setting
  4703. with_settings :link_copied_issue => 'yes' do
  4704. @request.session[:user_id] = 2
  4705. assert_difference 'Issue.count' do
  4706. assert_difference 'IssueRelation.count' do
  4707. post(
  4708. :create,
  4709. :params => {
  4710. :project_id => 1,
  4711. :copy_from => 1,
  4712. :issue => {
  4713. :subject => 'Copy'
  4714. }
  4715. }
  4716. )
  4717. end
  4718. end
  4719. end
  4720. end
  4721. def test_create_as_copy_should_never_add_relation_with_copied_issue_by_setting
  4722. with_settings :link_copied_issue => 'no' do
  4723. @request.session[:user_id] = 2
  4724. assert_difference 'Issue.count' do
  4725. assert_no_difference 'IssueRelation.count' do
  4726. post(
  4727. :create,
  4728. :params => {
  4729. :project_id => 1,
  4730. :copy_from => 1,
  4731. :link_copy => '1',
  4732. :issue => {
  4733. :subject => 'Copy'
  4734. }
  4735. }
  4736. )
  4737. end
  4738. end
  4739. end
  4740. end
  4741. def test_create_as_copy_should_copy_subtasks
  4742. @request.session[:user_id] = 2
  4743. issue = Issue.generate_with_descendants!
  4744. count = issue.descendants.count
  4745. assert_difference 'Issue.count', count + 1 do
  4746. post(
  4747. :create,
  4748. :params => {
  4749. :project_id => 1,
  4750. :copy_from => issue.id,
  4751. :issue => {
  4752. :project_id => '1',
  4753. :tracker_id => '3',
  4754. :status_id => '1',
  4755. :subject => 'Copy with subtasks'
  4756. },
  4757. :copy_subtasks => '1'
  4758. }
  4759. )
  4760. end
  4761. copy = Issue.where(:parent_id => nil).order('id DESC').first
  4762. assert_equal count, copy.descendants.count
  4763. assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
  4764. end
  4765. def test_create_as_copy_to_a_different_project_should_copy_subtask_custom_fields
  4766. issue = Issue.generate! {|i| i.custom_field_values = {'2' => 'Foo'}}
  4767. child = Issue.generate!(:parent_issue_id => issue.id) {|i| i.custom_field_values = {'2' => 'Bar'}}
  4768. @request.session[:user_id] = 1
  4769. assert_difference 'Issue.count', 2 do
  4770. post(
  4771. :create,
  4772. :params => {
  4773. :project_id => 'ecookbook',
  4774. :copy_from => issue.id,
  4775. :issue => {
  4776. :project_id => '2',
  4777. :tracker_id => 1,
  4778. :status_id => '1',
  4779. :subject => 'Copy with subtasks',
  4780. :custom_field_values => {
  4781. '2' => 'Foo'
  4782. }
  4783. },
  4784. :copy_subtasks => '1'
  4785. }
  4786. )
  4787. end
  4788. child_copy, issue_copy = Issue.order(:id => :desc).limit(2).to_a
  4789. assert_equal 2, issue_copy.project_id
  4790. assert_equal 'Foo', issue_copy.custom_field_value(2)
  4791. assert_equal 'Bar', child_copy.custom_field_value(2)
  4792. end
  4793. def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
  4794. @request.session[:user_id] = 2
  4795. issue = Issue.generate_with_descendants!
  4796. assert_difference 'Issue.count', 1 do
  4797. post(
  4798. :create,
  4799. :params => {
  4800. :project_id => 1,
  4801. :copy_from => 3,
  4802. :issue => {
  4803. :project_id => '1',
  4804. :tracker_id => '3',
  4805. :status_id => '1',
  4806. :subject => 'Copy with subtasks'
  4807. }
  4808. }
  4809. )
  4810. end
  4811. copy = Issue.where(:parent_id => nil).order('id DESC').first
  4812. assert_equal 0, copy.descendants.count
  4813. end
  4814. def test_create_as_copy_with_failure
  4815. @request.session[:user_id] = 2
  4816. post(
  4817. :create,
  4818. :params => {
  4819. :project_id => 1,
  4820. :copy_from => 1,
  4821. :issue => {
  4822. :project_id => '2',
  4823. :tracker_id => '3',
  4824. :status_id => '1',
  4825. :subject => ''
  4826. }
  4827. }
  4828. )
  4829. assert_response :success
  4830. assert_select 'form#issue-form[action="/projects/ecookbook/issues"]' do
  4831. assert_select 'select[name=?]', 'issue[project_id]' do
  4832. assert_select 'option[value="1"]:not([selected])', :text => 'eCookbook'
  4833. assert_select 'option[value="2"][selected=selected]', :text => 'OnlineStore'
  4834. end
  4835. assert_select 'input[name=copy_from][value="1"]'
  4836. end
  4837. end
  4838. def test_create_as_copy_on_project_without_permission_should_ignore_target_project
  4839. @request.session[:user_id] = 2
  4840. assert !User.find(2).member_of?(Project.find(4))
  4841. assert_difference 'Issue.count' do
  4842. post(
  4843. :create,
  4844. :params => {
  4845. :project_id => 1,
  4846. :copy_from => 1,
  4847. :issue => {
  4848. :project_id => '4',
  4849. :tracker_id => '3',
  4850. :status_id => '1',
  4851. :subject => 'Copy'
  4852. }
  4853. }
  4854. )
  4855. end
  4856. issue = Issue.order('id DESC').first
  4857. assert_equal 1, issue.project_id
  4858. end
  4859. def test_create_as_copy_with_watcher_user_ids_should_copy_watchers
  4860. @request.session[:user_id] = 2
  4861. copied = Issue.generate!
  4862. copied.add_watcher User.find(2)
  4863. copied.add_watcher User.find(3)
  4864. assert_difference 'Issue.count' do
  4865. post(
  4866. :create,
  4867. :params => {
  4868. :project_id => 1,
  4869. :copy_from => copied.id,
  4870. :issue => {
  4871. :subject => 'Copy cleared watchers',
  4872. :watcher_user_ids => ['', '3', '10']
  4873. }
  4874. }
  4875. )
  4876. end
  4877. issue = Issue.order('id DESC').first
  4878. assert_equal [3, 10], issue.watcher_user_ids.sort
  4879. end
  4880. def test_create_as_copy_without_watcher_user_ids_should_not_copy_watchers
  4881. @request.session[:user_id] = 2
  4882. copied = Issue.generate!
  4883. copied.add_watcher User.find(2)
  4884. copied.add_watcher User.find(3)
  4885. assert_difference 'Issue.count' do
  4886. post(
  4887. :create,
  4888. :params => {
  4889. :project_id => 1,
  4890. :copy_from => copied.id,
  4891. :issue => {
  4892. :subject => 'Copy cleared watchers',
  4893. :watcher_user_ids => ['']
  4894. }
  4895. }
  4896. )
  4897. end
  4898. issue = Issue.order('id DESC').first
  4899. assert_equal [], issue.watcher_user_ids
  4900. end
  4901. def test_get_edit
  4902. @request.session[:user_id] = 2
  4903. get(:edit, :params => {:id => 1})
  4904. assert_response :success
  4905. assert_select 'select[name=?]', 'issue[project_id]'
  4906. # Be sure we don't display inactive IssuePriorities
  4907. assert ! IssuePriority.find(15).active?
  4908. assert_select 'select[name=?]', 'issue[priority_id]' do
  4909. assert_select 'option[value="15"]', 0
  4910. end
  4911. assert_select 'span.icon-warning', 0
  4912. end
  4913. def test_edit_should_hide_project_if_user_is_not_allowed_to_change_project
  4914. WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :field_name => 'project_id', :rule => 'readonly')
  4915. @request.session[:user_id] = 2
  4916. get(:edit, :params => {:id => 1})
  4917. assert_response :success
  4918. assert_select 'select[name=?]', 'issue[project_id]', 0
  4919. end
  4920. def test_edit_should_not_hide_project_when_user_changes_the_project_even_if_project_is_readonly_on_target_project
  4921. WorkflowPermission.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :field_name => 'project_id', :rule => 'readonly')
  4922. issue = Issue.generate!(:project_id => 2)
  4923. @request.session[:user_id] = 2
  4924. get(
  4925. :edit,
  4926. :params => {
  4927. :id => issue.id,
  4928. :issue => {
  4929. :project_id => 1
  4930. }
  4931. }
  4932. )
  4933. assert_response :success
  4934. assert_select 'select[name=?]', 'issue[project_id]'
  4935. end
  4936. def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
  4937. @request.session[:user_id] = 2
  4938. Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
  4939. get(:edit, :params => {:id => 1})
  4940. assert_select 'input[name=?]', 'time_entry[hours]'
  4941. end
  4942. def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
  4943. @request.session[:user_id] = 2
  4944. Role.find_by_name('Manager').remove_permission! :log_time
  4945. get(:edit, :params => {:id => 1})
  4946. assert_select 'input[name=?]', 'time_entry[hours]', 0
  4947. end
  4948. def test_get_edit_with_params
  4949. @request.session[:user_id] = 2
  4950. get(
  4951. :edit,
  4952. :params => {
  4953. :id => 1,
  4954. :issue => {
  4955. :status_id => 5,
  4956. :priority_id => 7
  4957. },
  4958. :time_entry => {
  4959. :hours => '2.5',
  4960. :comments => 'test_get_edit_with_params',
  4961. :activity_id => 10
  4962. }
  4963. }
  4964. )
  4965. assert_response :success
  4966. assert_select 'select[name=?]', 'issue[status_id]' do
  4967. assert_select 'option[value="5"][selected=selected]', :text => 'Closed'
  4968. end
  4969. assert_select 'select[name=?]', 'issue[priority_id]' do
  4970. assert_select 'option[value="7"][selected=selected]', :text => 'Urgent'
  4971. end
  4972. assert_select 'input[name=?][value="2.50"]', 'time_entry[hours]'
  4973. assert_select 'select[name=?]', 'time_entry[activity_id]' do
  4974. assert_select 'option[value="10"][selected=selected]', :text => 'Development'
  4975. end
  4976. assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
  4977. end
  4978. def test_get_edit_with_multi_custom_field
  4979. field = CustomField.find(1)
  4980. field.update_attribute :multiple, true
  4981. issue = Issue.find(1)
  4982. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  4983. issue.save!
  4984. @request.session[:user_id] = 2
  4985. get(:edit, :params => {:id => 1})
  4986. assert_response :success
  4987. assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
  4988. assert_select 'option', 3
  4989. assert_select 'option[value=MySQL][selected=selected]'
  4990. assert_select 'option[value=Oracle][selected=selected]'
  4991. assert_select 'option[value=PostgreSQL]:not([selected])'
  4992. end
  4993. end
  4994. def test_get_edit_with_me_assigned_to_id
  4995. @request.session[:user_id] = 2
  4996. get(
  4997. :edit,
  4998. :params => {
  4999. :id => 1,
  5000. :issue => {:assigned_to_id => 'me'}
  5001. }
  5002. )
  5003. assert_response :success
  5004. assert_select 'select[name=?]', 'issue[assigned_to_id]' do
  5005. assert_select 'option[value="2"][selected=selected]'
  5006. end
  5007. end
  5008. def test_get_edit_for_issue_with_transition_warning_should_show_the_warning
  5009. @request.session[:user_id] = 2
  5010. get(
  5011. :edit,
  5012. :params => {
  5013. :id => 9,
  5014. }
  5015. )
  5016. assert_response :success
  5017. reason = l(:notice_issue_not_closable_by_blocking_issue)
  5018. assert_select 'span.icon-warning[title=?]', reason, :text => reason
  5019. end
  5020. def test_update_form_for_existing_issue
  5021. @request.session[:user_id] = 2
  5022. patch(
  5023. :edit,
  5024. :params => {
  5025. :id => 1,
  5026. :issue => {
  5027. :tracker_id => 2,
  5028. :subject => 'This is the test_new issue',
  5029. :description => 'This is the description',
  5030. :priority_id => 5
  5031. }
  5032. },
  5033. :xhr => true
  5034. )
  5035. assert_response :success
  5036. assert_equal 'text/javascript', response.media_type
  5037. assert_include 'This is the test_new issue', response.body
  5038. end
  5039. def test_update_form_for_existing_issue_should_keep_issue_author
  5040. @request.session[:user_id] = 3
  5041. patch(
  5042. :edit,
  5043. :params => {
  5044. :id => 1,
  5045. :issue => {
  5046. :subject => 'Changed'
  5047. }
  5048. }
  5049. )
  5050. assert_response :success
  5051. assert_equal User.find(2), Issue.find(1).author
  5052. end
  5053. def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
  5054. @request.session[:user_id] = 2
  5055. WorkflowTransition.delete_all
  5056. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
  5057. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
  5058. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
  5059. patch(
  5060. :edit,
  5061. :params => {
  5062. :id => 2,
  5063. :issue => {
  5064. :tracker_id => 2,
  5065. :status_id => 5,
  5066. :subject => 'This is an issue'
  5067. }
  5068. }
  5069. )
  5070. assert_select 'select[name=?]', 'issue[status_id]' do
  5071. assert_select 'option[value="1"]'
  5072. assert_select 'option[value="2"]'
  5073. assert_select 'option[value="5"][selected=selected]'
  5074. assert_select 'option', 3
  5075. end
  5076. end
  5077. def test_update_form_for_existing_issue_with_project_change
  5078. @request.session[:user_id] = 2
  5079. patch(
  5080. :edit,
  5081. :params => {
  5082. :id => 1,
  5083. :issue => {
  5084. :project_id => 2,
  5085. :tracker_id => 2,
  5086. :subject => 'This is the test_new issue',
  5087. :description => 'This is the description',
  5088. :priority_id => 5
  5089. }
  5090. }
  5091. )
  5092. assert_response :success
  5093. assert_select 'select[name=?]', 'issue[project_id]' do
  5094. assert_select 'option[value="2"][selected=selected]'
  5095. end
  5096. assert_select 'select[name=?]', 'issue[tracker_id]' do
  5097. assert_select 'option[value="2"][selected=selected]'
  5098. end
  5099. assert_select 'input[name=?][value=?]', 'issue[subject]', 'This is the test_new issue'
  5100. end
  5101. def test_update_form_should_keep_category_with_same_when_changing_project
  5102. source = Project.generate!
  5103. target = Project.generate!
  5104. source_category = IssueCategory.create!(:name => 'Foo', :project => source)
  5105. target_category = IssueCategory.create!(:name => 'Foo', :project => target)
  5106. issue = Issue.generate!(:project => source, :category => source_category)
  5107. @request.session[:user_id] = 1
  5108. patch(
  5109. :edit,
  5110. :params => {
  5111. :id => issue.id,
  5112. :issue => {
  5113. :project_id => target.id,
  5114. :category_id => source_category.id
  5115. }
  5116. }
  5117. )
  5118. assert_response :success
  5119. assert_select 'select[name=?]', 'issue[category_id]' do
  5120. assert_select 'option[value=?][selected=selected]', target_category.id.to_s
  5121. end
  5122. end
  5123. def test_update_form_should_propose_default_status_for_existing_issue
  5124. @request.session[:user_id] = 2
  5125. WorkflowTransition.delete_all
  5126. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
  5127. patch(:edit, :params => {:id => 2})
  5128. assert_response :success
  5129. assert_select 'select[name=?]', 'issue[status_id]' do
  5130. assert_select 'option[value="2"]'
  5131. assert_select 'option[value="3"]'
  5132. assert_select 'option', 2
  5133. end
  5134. end
  5135. def test_put_update_without_custom_fields_param
  5136. @request.session[:user_id] = 2
  5137. issue = Issue.find(1)
  5138. assert_equal '125', issue.custom_value_for(2).value
  5139. assert_difference('Journal.count') do
  5140. assert_difference('JournalDetail.count') do
  5141. put(
  5142. :update,
  5143. :params => {
  5144. :id => 1,
  5145. :issue => {
  5146. :subject => 'New subject'
  5147. }
  5148. }
  5149. )
  5150. end
  5151. end
  5152. assert_redirected_to :action => 'show', :id => '1'
  5153. issue.reload
  5154. assert_equal 'New subject', issue.subject
  5155. # Make sure custom fields were not cleared
  5156. assert_equal '125', issue.custom_value_for(2).value
  5157. end
  5158. def test_put_update_with_project_change
  5159. @request.session[:user_id] = 2
  5160. ActionMailer::Base.deliveries.clear
  5161. with_settings :notified_events => %w(issue_updated) do
  5162. assert_difference('Journal.count') do
  5163. assert_difference('JournalDetail.count', 3) do
  5164. put(
  5165. :update,
  5166. :params => {
  5167. :id => 1,
  5168. :issue => {
  5169. :project_id => '2',
  5170. :tracker_id => '1', # no change
  5171. :priority_id => '6',
  5172. :category_id => '3'
  5173. }
  5174. }
  5175. )
  5176. end
  5177. end
  5178. end
  5179. assert_redirected_to :action => 'show', :id => '1'
  5180. issue = Issue.find(1)
  5181. assert_equal 2, issue.project_id
  5182. assert_equal 1, issue.tracker_id
  5183. assert_equal 6, issue.priority_id
  5184. assert_equal 3, issue.category_id
  5185. mail = ActionMailer::Base.deliveries.last
  5186. assert_not_nil mail
  5187. assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
  5188. assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
  5189. end
  5190. def test_put_update_trying_to_move_issue_to_project_without_tracker_should_not_error
  5191. target = Project.generate!(:tracker_ids => [])
  5192. assert target.trackers.empty?
  5193. issue = Issue.generate!
  5194. @request.session[:user_id] = 1
  5195. put(
  5196. :update,
  5197. :params => {
  5198. :id => issue.id,
  5199. :issue => {
  5200. :project_id => target.id
  5201. }
  5202. }
  5203. )
  5204. assert_response 302
  5205. end
  5206. def test_put_update_with_tracker_change
  5207. @request.session[:user_id] = 2
  5208. ActionMailer::Base.deliveries.clear
  5209. with_settings :notified_events => %w(issue_updated) do
  5210. assert_difference('Journal.count') do
  5211. assert_difference('JournalDetail.count', 3) do
  5212. put(
  5213. :update,
  5214. :params => {
  5215. :id => 1,
  5216. :issue => {
  5217. :project_id => '1',
  5218. :tracker_id => '2',
  5219. :priority_id => '6'
  5220. }
  5221. }
  5222. )
  5223. end
  5224. end
  5225. end
  5226. assert_redirected_to :action => 'show', :id => '1'
  5227. issue = Issue.find(1)
  5228. assert_equal 1, issue.project_id
  5229. assert_equal 2, issue.tracker_id
  5230. assert_equal 6, issue.priority_id
  5231. assert_equal 1, issue.category_id
  5232. mail = ActionMailer::Base.deliveries.last
  5233. assert_not_nil mail
  5234. assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
  5235. assert_mail_body_match "Tracker changed from Bug to Feature request", mail
  5236. end
  5237. def test_put_update_with_custom_field_change
  5238. @request.session[:user_id] = 2
  5239. issue = Issue.find(1)
  5240. assert_equal '125', issue.custom_value_for(2).value
  5241. with_settings :notified_events => %w(issue_updated) do
  5242. assert_difference('Journal.count') do
  5243. assert_difference('JournalDetail.count', 3) do
  5244. put(
  5245. :update,
  5246. :params => {
  5247. :id => 1,
  5248. :issue => {
  5249. :subject => 'Custom field change',
  5250. :priority_id => '6',
  5251. :category_id => '1', # no change
  5252. :custom_field_values => {'2' => 'New custom value'}
  5253. }
  5254. }
  5255. )
  5256. end
  5257. end
  5258. end
  5259. assert_redirected_to :action => 'show', :id => '1'
  5260. issue.reload
  5261. assert_equal 'New custom value', issue.custom_value_for(2).value
  5262. mail = ActionMailer::Base.deliveries.last
  5263. assert_not_nil mail
  5264. assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
  5265. end
  5266. def test_put_update_with_multi_custom_field_change
  5267. field = CustomField.find(1)
  5268. field.update_attribute :multiple, true
  5269. issue = Issue.find(1)
  5270. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  5271. issue.save!
  5272. @request.session[:user_id] = 2
  5273. assert_difference('Journal.count') do
  5274. assert_difference('JournalDetail.count', 3) do
  5275. put(
  5276. :update,
  5277. :params => {
  5278. :id => 1,
  5279. :issue => {
  5280. :subject => 'Custom field change',
  5281. :custom_field_values => {
  5282. '1' => ['', 'Oracle', 'PostgreSQL']
  5283. }
  5284. }
  5285. }
  5286. )
  5287. end
  5288. end
  5289. assert_redirected_to :action => 'show', :id => '1'
  5290. assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
  5291. end
  5292. def test_put_update_with_status_and_assignee_change
  5293. issue = Issue.find(1)
  5294. assert_equal 1, issue.status_id
  5295. @request.session[:user_id] = 2
  5296. with_settings :notified_events => %w(issue_updated) do
  5297. assert_difference('TimeEntry.count', 0) do
  5298. put(
  5299. :update,
  5300. :params => {
  5301. :id => 1,
  5302. :issue => {
  5303. :status_id => 2,
  5304. :assigned_to_id => 3,
  5305. :notes => 'Assigned to dlopper'
  5306. },
  5307. :time_entry => {
  5308. :hours => '',
  5309. :comments => '',
  5310. :activity_id => TimeEntryActivity.first
  5311. }
  5312. }
  5313. )
  5314. end
  5315. end
  5316. assert_redirected_to :action => 'show', :id => '1'
  5317. issue.reload
  5318. assert_equal 2, issue.status_id
  5319. j = Journal.order('id DESC').first
  5320. assert_equal 'Assigned to dlopper', j.notes
  5321. assert_equal 2, j.details.size
  5322. mail = ActionMailer::Base.deliveries.last
  5323. assert_mail_body_match "Status changed from New to Assigned", mail
  5324. # subject should contain the new status
  5325. assert mail.subject.include?("(#{IssueStatus.find(2).name})")
  5326. end
  5327. def test_put_update_with_note_only
  5328. notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
  5329. with_settings :notified_events => %w(issue_updated) do
  5330. # anonymous user
  5331. put(
  5332. :update,
  5333. :params => {
  5334. :id => 1,
  5335. :issue => {
  5336. :notes => notes
  5337. }
  5338. }
  5339. )
  5340. end
  5341. assert_redirected_to :action => 'show', :id => '1'
  5342. j = Journal.order('id DESC').first
  5343. assert_equal notes, j.notes
  5344. assert_equal 0, j.details.size
  5345. assert_equal User.anonymous, j.user
  5346. mail = ActionMailer::Base.deliveries.last
  5347. assert_mail_body_match notes, mail
  5348. end
  5349. def test_put_update_with_private_note_only
  5350. notes = 'Private note'
  5351. @request.session[:user_id] = 2
  5352. assert_difference 'Journal.count' do
  5353. put(
  5354. :update,
  5355. :params => {
  5356. :id => 1,
  5357. :issue => {
  5358. :notes => notes,
  5359. :private_notes => '1'
  5360. }
  5361. }
  5362. )
  5363. assert_redirected_to :action => 'show', :id => '1'
  5364. end
  5365. j = Journal.order('id DESC').first
  5366. assert_equal notes, j.notes
  5367. assert_equal true, j.private_notes
  5368. end
  5369. def test_put_update_with_private_note_and_changes
  5370. notes = 'Private note'
  5371. @request.session[:user_id] = 2
  5372. assert_difference 'Journal.count', 2 do
  5373. put(
  5374. :update,
  5375. :params => {
  5376. :id => 1,
  5377. :issue => {
  5378. :subject => 'New subject',
  5379. :notes => notes,
  5380. :private_notes => '1'
  5381. }
  5382. }
  5383. )
  5384. assert_redirected_to :action => 'show', :id => '1'
  5385. end
  5386. j = Journal.order('id DESC').first
  5387. assert_equal notes, j.notes
  5388. assert_equal true, j.private_notes
  5389. assert_equal 0, j.details.count
  5390. j = Journal.order('id DESC').offset(1).first
  5391. assert_nil j.notes
  5392. assert_equal false, j.private_notes
  5393. assert_equal 1, j.details.count
  5394. end
  5395. def test_put_update_with_note_and_spent_time
  5396. @request.session[:user_id] = 2
  5397. spent_hours_before = Issue.find(1).spent_hours
  5398. assert_difference('TimeEntry.count') do
  5399. put(
  5400. :update,
  5401. :params => {
  5402. :id => 1,
  5403. :issue => {
  5404. :notes => '2.5 hours added'
  5405. },
  5406. :time_entry => {
  5407. :hours => '2.5',
  5408. :comments => 'test_put_update_with_note_and_spent_time',
  5409. :activity_id => TimeEntryActivity.first.id
  5410. }
  5411. }
  5412. )
  5413. end
  5414. assert_redirected_to :action => 'show', :id => '1'
  5415. issue = Issue.find(1)
  5416. j = Journal.order('id DESC').first
  5417. assert_equal '2.5 hours added', j.notes
  5418. assert_equal 0, j.details.size
  5419. t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
  5420. assert_not_nil t
  5421. assert_equal 2.5, t.hours
  5422. assert_equal spent_hours_before + 2.5, issue.spent_hours
  5423. end
  5424. def test_put_update_should_check_add_issue_notes_permission
  5425. role = Role.find(1)
  5426. role.remove_permission! :add_issue_notes
  5427. @request.session[:user_id] = 2
  5428. assert_no_difference 'Journal.count' do
  5429. put(
  5430. :update,
  5431. :params => {
  5432. :id => 1,
  5433. :issue => {
  5434. :notes => 'New note'
  5435. }
  5436. }
  5437. )
  5438. end
  5439. end
  5440. def test_put_update_should_preserve_parent_issue_even_if_not_visible
  5441. parent = Issue.generate!(:project_id => 1, :is_private => true)
  5442. issue = Issue.generate!(:parent_issue_id => parent.id)
  5443. assert !parent.visible?(User.find(3))
  5444. @request.session[:user_id] = 3
  5445. get(:edit, :params => {:id => issue.id})
  5446. assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
  5447. put(
  5448. :update,
  5449. :params => {
  5450. :id => issue.id,
  5451. :issue => {
  5452. :subject => 'New subject',
  5453. :parent_issue_id => parent.id.to_s
  5454. }
  5455. }
  5456. )
  5457. assert_response 302
  5458. assert_equal parent, issue.parent
  5459. end
  5460. def test_put_update_with_attachment_only
  5461. set_tmp_attachments_directory
  5462. # Delete all fixtured journals, a race condition can occur causing the wrong
  5463. # journal to get fetched in the next find.
  5464. Journal.delete_all
  5465. JournalDetail.delete_all
  5466. with_settings :notified_events => %w(issue_updated) do
  5467. # anonymous user
  5468. assert_difference 'Attachment.count' do
  5469. put(
  5470. :update,
  5471. :params => {
  5472. :id => 1,
  5473. :issue => {
  5474. :notes => ''
  5475. },
  5476. :attachments => {
  5477. '1' => {
  5478. 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
  5479. 'description' => 'test file'
  5480. }
  5481. }
  5482. }
  5483. )
  5484. end
  5485. end
  5486. assert_redirected_to :action => 'show', :id => '1'
  5487. j = Issue.find(1).journals.reorder('id DESC').first
  5488. assert j.notes.blank?
  5489. assert_equal 1, j.details.size
  5490. assert_equal 'testfile.txt', j.details.first.value
  5491. assert_equal User.anonymous, j.user
  5492. attachment = Attachment.order('id DESC').first
  5493. assert_equal Issue.find(1), attachment.container
  5494. assert_equal User.anonymous, attachment.author
  5495. assert_equal 'testfile.txt', attachment.filename
  5496. assert_equal 'text/plain', attachment.content_type
  5497. assert_equal 'test file', attachment.description
  5498. assert_equal 59, attachment.filesize
  5499. assert File.exists?(attachment.diskfile)
  5500. assert_equal 59, File.size(attachment.diskfile)
  5501. mail = ActionMailer::Base.deliveries.last
  5502. assert_mail_body_match 'testfile.txt', mail
  5503. end
  5504. def test_put_update_with_failure_should_save_attachments
  5505. set_tmp_attachments_directory
  5506. @request.session[:user_id] = 2
  5507. assert_no_difference 'Journal.count' do
  5508. assert_difference 'Attachment.count' do
  5509. put(
  5510. :update,
  5511. :params => {
  5512. :id => 1,
  5513. :issue => {
  5514. :subject => ''
  5515. },
  5516. :attachments => {
  5517. '1' => {
  5518. 'file' => uploaded_test_file('testfile.txt', 'text/plain'),
  5519. 'description' => 'test file'
  5520. }
  5521. }
  5522. }
  5523. )
  5524. assert_response :success
  5525. end
  5526. end
  5527. attachment = Attachment.order('id DESC').first
  5528. assert_equal 'testfile.txt', attachment.filename
  5529. assert File.exists?(attachment.diskfile)
  5530. assert_nil attachment.container
  5531. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  5532. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  5533. end
  5534. def test_put_update_with_failure_should_keep_saved_attachments
  5535. set_tmp_attachments_directory
  5536. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  5537. @request.session[:user_id] = 2
  5538. assert_no_difference 'Journal.count' do
  5539. assert_no_difference 'Attachment.count' do
  5540. put(
  5541. :update,
  5542. :params => {
  5543. :id => 1,
  5544. :issue => {
  5545. :subject => ''
  5546. },
  5547. :attachments => {
  5548. 'p0' => {
  5549. 'token' => attachment.token
  5550. }
  5551. }
  5552. }
  5553. )
  5554. assert_response :success
  5555. end
  5556. end
  5557. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  5558. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  5559. end
  5560. def test_put_update_should_attach_saved_attachments
  5561. set_tmp_attachments_directory
  5562. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  5563. @request.session[:user_id] = 2
  5564. assert_difference 'Journal.count' do
  5565. assert_difference 'JournalDetail.count' do
  5566. assert_no_difference 'Attachment.count' do
  5567. put(
  5568. :update,
  5569. :params => {
  5570. :id => 1,
  5571. :issue => {
  5572. :notes => 'Attachment added'
  5573. },
  5574. :attachments => {
  5575. 'p0' => {
  5576. 'token' => attachment.token
  5577. }
  5578. }
  5579. }
  5580. )
  5581. assert_redirected_to '/issues/1'
  5582. end
  5583. end
  5584. end
  5585. attachment.reload
  5586. assert_equal Issue.find(1), attachment.container
  5587. journal = Journal.order('id DESC').first
  5588. assert_equal 1, journal.details.size
  5589. assert_equal 'testfile.txt', journal.details.first.value
  5590. end
  5591. def test_put_update_with_attachment_that_fails_to_save
  5592. set_tmp_attachments_directory
  5593. # anonymous user
  5594. with_settings :attachment_max_size => 0 do
  5595. put(
  5596. :update,
  5597. :params => {
  5598. :id => 1,
  5599. :issue => {
  5600. :notes => ''
  5601. },
  5602. :attachments => {
  5603. '1' => {
  5604. 'file' => uploaded_test_file('testfile.txt', 'text/plain')
  5605. }
  5606. }
  5607. }
  5608. )
  5609. assert_redirected_to :action => 'show', :id => '1'
  5610. assert_equal '1 file(s) could not be saved.', flash[:warning]
  5611. end
  5612. end
  5613. def test_put_update_with_attachment_deletion_should_create_a_single_journal
  5614. set_tmp_attachments_directory
  5615. ActionMailer::Base.deliveries.clear
  5616. @request.session[:user_id] = 2
  5617. journal = new_record(Journal) do
  5618. assert_difference 'Attachment.count', -2 do
  5619. put(
  5620. :update,
  5621. :params => {
  5622. :id => 3,
  5623. :issue => {
  5624. :notes => 'Removing attachments',
  5625. :deleted_attachment_ids => ['1', '5']
  5626. }
  5627. }
  5628. )
  5629. end
  5630. end
  5631. assert_equal 'Removing attachments', journal.notes
  5632. assert_equal 2, journal.details.count
  5633. assert_select_email do
  5634. assert_select 'ul.journal.details li', 2
  5635. assert_select 'del', :text => 'error281.txt'
  5636. assert_select 'del', :text => 'changeset_iso8859-1.diff'
  5637. end
  5638. end
  5639. def test_put_update_with_attachment_deletion_and_failure_should_preserve_selected_attachments
  5640. set_tmp_attachments_directory
  5641. @request.session[:user_id] = 2
  5642. assert_no_difference 'Journal.count' do
  5643. assert_no_difference 'Attachment.count' do
  5644. put(
  5645. :update,
  5646. :params => {
  5647. :id => 3,
  5648. :issue => {
  5649. :subject => '',
  5650. :notes => 'Removing attachments',
  5651. :deleted_attachment_ids => ['1', '5']
  5652. }
  5653. }
  5654. )
  5655. end
  5656. end
  5657. assert_select 'input[name=?][value="1"][checked=checked]', 'issue[deleted_attachment_ids][]'
  5658. assert_select 'input[name=?][value="5"][checked=checked]', 'issue[deleted_attachment_ids][]'
  5659. assert_select 'input[name=?][value="6"]:not([checked])', 'issue[deleted_attachment_ids][]'
  5660. end
  5661. def test_put_update_with_no_change
  5662. issue = Issue.find(1)
  5663. issue.journals.clear
  5664. ActionMailer::Base.deliveries.clear
  5665. put(
  5666. :update,
  5667. :params => {
  5668. :id => 1,
  5669. :issue => {
  5670. :notes => ''
  5671. }
  5672. }
  5673. )
  5674. assert_redirected_to :action => 'show', :id => '1'
  5675. issue.reload
  5676. assert issue.journals.empty?
  5677. # No email should be sent
  5678. assert ActionMailer::Base.deliveries.empty?
  5679. end
  5680. def test_put_update_should_send_a_notification
  5681. @request.session[:user_id] = 2
  5682. ActionMailer::Base.deliveries.clear
  5683. issue = Issue.find(1)
  5684. old_subject = issue.subject
  5685. new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
  5686. with_settings :notified_events => %w(issue_updated) do
  5687. put(
  5688. :update,
  5689. :params => {
  5690. :id => 1,
  5691. :issue => {
  5692. :subject => new_subject,
  5693. :priority_id => '6',
  5694. :category_id => '1' # no change
  5695. }
  5696. }
  5697. )
  5698. assert_equal 2, ActionMailer::Base.deliveries.size
  5699. end
  5700. end
  5701. def test_put_update_with_invalid_spent_time_hours_only
  5702. @request.session[:user_id] = 2
  5703. notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
  5704. assert_no_difference('Journal.count') do
  5705. put(
  5706. :update,
  5707. :params => {
  5708. :id => 1,
  5709. :issue => {
  5710. :notes => notes
  5711. },
  5712. :time_entry => {
  5713. "comments"=>"", "activity_id"=>"", "hours"=>"2z"
  5714. }
  5715. }
  5716. )
  5717. end
  5718. assert_response :success
  5719. assert_select_error /Activity cannot be blank/
  5720. assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
  5721. assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
  5722. end
  5723. def test_put_update_with_invalid_spent_time_comments_only
  5724. @request.session[:user_id] = 2
  5725. notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
  5726. assert_no_difference('Journal.count') do
  5727. put(
  5728. :update,
  5729. :params => {
  5730. :id => 1,
  5731. :issue => {
  5732. :notes => notes
  5733. },
  5734. :time_entry => {
  5735. "comments"=>"this is my comment", "activity_id"=>"", "hours"=>""
  5736. }
  5737. }
  5738. )
  5739. end
  5740. assert_response :success
  5741. assert_select_error /Activity cannot be blank/
  5742. assert_select_error /Hours cannot be blank/
  5743. assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
  5744. assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
  5745. end
  5746. def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
  5747. issue = Issue.find(2)
  5748. @request.session[:user_id] = 2
  5749. put(
  5750. :update,
  5751. :params => {
  5752. :id => issue.id,
  5753. :issue => {
  5754. :fixed_version_id => 4
  5755. }
  5756. }
  5757. )
  5758. assert_response :redirect
  5759. issue.reload
  5760. assert_equal 4, issue.fixed_version_id
  5761. assert_not_equal issue.project_id, issue.fixed_version.project_id
  5762. end
  5763. def test_put_update_should_redirect_back_using_the_back_url_parameter
  5764. issue = Issue.find(2)
  5765. @request.session[:user_id] = 2
  5766. put(
  5767. :update,
  5768. :params => {
  5769. :id => issue.id,
  5770. :issue => {
  5771. :fixed_version_id => 4
  5772. },
  5773. :back_url => '/issues'
  5774. }
  5775. )
  5776. assert_response :redirect
  5777. assert_redirected_to '/issues'
  5778. end
  5779. def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
  5780. issue = Issue.find(2)
  5781. @request.session[:user_id] = 2
  5782. put(
  5783. :update,
  5784. :params => {
  5785. :id => issue.id,
  5786. :issue => {
  5787. :fixed_version_id => 4
  5788. },
  5789. :back_url => 'http://google.com'
  5790. }
  5791. )
  5792. assert_response :redirect
  5793. assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
  5794. end
  5795. def test_put_update_should_redirect_with_previous_and_next_issue_ids_params
  5796. @request.session[:user_id] = 2
  5797. put(
  5798. :update,
  5799. :params => {
  5800. :id => 11,
  5801. :issue => {
  5802. :status_id => 6,
  5803. :notes => 'Notes'
  5804. },
  5805. :prev_issue_id => 8,
  5806. :next_issue_id => 12,
  5807. :issue_position => 2,
  5808. :issue_count => 3
  5809. }
  5810. )
  5811. assert_redirected_to '/issues/11?issue_count=3&issue_position=2&next_issue_id=12&prev_issue_id=8'
  5812. end
  5813. def test_update_with_permission_on_tracker_should_be_allowed
  5814. role = Role.find(1)
  5815. role.set_permission_trackers :edit_issues, [1]
  5816. role.save!
  5817. issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Original subject')
  5818. @request.session[:user_id] = 2
  5819. put(
  5820. :update,
  5821. :params => {
  5822. :id => issue.id,
  5823. :issue => {
  5824. :subject => 'Changed subject'
  5825. }
  5826. }
  5827. )
  5828. assert_response 302
  5829. assert_equal 'Changed subject', issue.reload.subject
  5830. end
  5831. def test_update_without_permission_on_tracker_should_be_denied
  5832. role = Role.find(1)
  5833. role.set_permission_trackers :edit_issues, [1]
  5834. role.save!
  5835. issue = Issue.generate!(:project_id => 1, :tracker_id => 2, :subject => 'Original subject')
  5836. @request.session[:user_id] = 2
  5837. put(
  5838. :update,
  5839. :params => {
  5840. :id => issue.id,
  5841. :issue => {
  5842. :subject => 'Changed subject'
  5843. }
  5844. }
  5845. )
  5846. assert_response 302
  5847. assert_equal 'Original subject', issue.reload.subject
  5848. end
  5849. def test_update_with_me_assigned_to_id
  5850. @request.session[:user_id] = 2
  5851. issue = Issue.find(1)
  5852. assert_not_equal 2, issue.assigned_to_id
  5853. put(
  5854. :update,
  5855. :params => {
  5856. :id => issue.id,
  5857. :issue => {
  5858. :assigned_to_id => 'me'
  5859. }
  5860. }
  5861. )
  5862. assert_response 302
  5863. assert_equal 2, issue.reload.assigned_to_id
  5864. end
  5865. def test_get_bulk_edit
  5866. @request.session[:user_id] = 2
  5867. get(:bulk_edit, :params => {:ids => [1, 3]})
  5868. assert_response :success
  5869. assert_select 'ul#bulk-selection' do
  5870. assert_select 'li', 2
  5871. assert_select 'li a', :text => 'Bug #1'
  5872. end
  5873. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  5874. assert_select 'input[name=?]', 'ids[]', 2
  5875. assert_select 'input[name=?][value="1"][type=hidden]', 'ids[]'
  5876. assert_select 'select[name=?]', 'issue[project_id]'
  5877. assert_select 'input[name=?]', 'issue[parent_issue_id]'
  5878. # Project specific custom field, date type
  5879. field = CustomField.find(9)
  5880. assert !field.is_for_all?
  5881. assert_equal 'date', field.field_format
  5882. assert_select 'input[name=?]', 'issue[custom_field_values][9]'
  5883. # System wide custom field
  5884. assert CustomField.find(1).is_for_all?
  5885. assert_select 'select[name=?]', 'issue[custom_field_values][1]'
  5886. # Be sure we don't display inactive IssuePriorities
  5887. assert ! IssuePriority.find(15).active?
  5888. assert_select 'select[name=?]', 'issue[priority_id]' do
  5889. assert_select 'option[value="15"]', 0
  5890. end
  5891. # Initial form should hide 'follow' button
  5892. assert_select 'input[type=submit]', 1 do
  5893. assert_select '[name=?]', 'commit', 1
  5894. assert_select '[name=?]', 'follow', 0
  5895. end
  5896. end
  5897. end
  5898. test "bulk_edit should show follow button when project is selected" do
  5899. @request.session[:user_id] = 2
  5900. post(
  5901. :bulk_edit,
  5902. :params => {
  5903. :ids => [1, 3],
  5904. :issue => {
  5905. :project_id => 2,
  5906. }
  5907. }
  5908. )
  5909. assert_response :success
  5910. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  5911. assert_select 'input[type=submit]', 2 do
  5912. assert_select '[name=?]', 'commit', 1
  5913. assert_select '[name=?]', 'follow', 1
  5914. end
  5915. end
  5916. end
  5917. test "bulk_edit should hide follow button when project is not changed" do
  5918. @request.session[:user_id] = 2
  5919. post(
  5920. :bulk_edit,
  5921. :params => {
  5922. :ids => [1, 3],
  5923. :issue => {
  5924. :project_id => "",
  5925. }
  5926. }
  5927. )
  5928. assert_response :success
  5929. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  5930. assert_select 'input[type=submit]', 1 do
  5931. assert_select '[name=?]', 'commit', 1
  5932. assert_select '[name=?]', 'follow', 0
  5933. end
  5934. end
  5935. end
  5936. def test_get_bulk_edit_on_different_projects
  5937. @request.session[:user_id] = 2
  5938. get(:bulk_edit, :params => {:ids => [1, 2, 6]})
  5939. assert_response :success
  5940. # Can not set issues from different projects as children of an issue
  5941. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  5942. # Project specific custom field, date type
  5943. field = CustomField.find(9)
  5944. assert !field.is_for_all?
  5945. assert !field.project_ids.include?(Issue.find(6).project_id)
  5946. assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
  5947. end
  5948. def test_get_bulk_edit_with_user_custom_field
  5949. field =
  5950. IssueCustomField.
  5951. create!(
  5952. :name => 'Tester',
  5953. :field_format => 'user',
  5954. :is_for_all => true,
  5955. :tracker_ids => [1, 2, 3]
  5956. )
  5957. @request.session[:user_id] = 2
  5958. get(:bulk_edit, :params => {:ids => [1, 2]})
  5959. assert_response :success
  5960. assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
  5961. assert_select 'option', Project.find(1).users.count + 3 # "no change" + "none" + "me" options
  5962. end
  5963. end
  5964. def test_get_bulk_edit_with_version_custom_field
  5965. field =
  5966. IssueCustomField.
  5967. create!(
  5968. :name => 'Affected version',
  5969. :field_format => 'version',
  5970. :is_for_all => true,
  5971. :tracker_ids => [1, 2, 3]
  5972. )
  5973. @request.session[:user_id] = 2
  5974. get(:bulk_edit, :params => {:ids => [1, 2]})
  5975. assert_response :success
  5976. assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
  5977. assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
  5978. end
  5979. end
  5980. def test_get_bulk_edit_with_multi_custom_field
  5981. field = CustomField.find(1)
  5982. field.update_attribute :multiple, true
  5983. @request.session[:user_id] = 2
  5984. get(:bulk_edit, :params => {:ids => [1, 3]})
  5985. assert_response :success
  5986. assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
  5987. assert_select 'option', field.possible_values.size + 1 # "none" options
  5988. end
  5989. end
  5990. def test_bulk_edit_should_propose_to_clear_text_custom_fields
  5991. @request.session[:user_id] = 2
  5992. get(:bulk_edit, :params => {:ids => [1, 3]})
  5993. assert_response :success
  5994. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', '__none__'
  5995. end
  5996. def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
  5997. WorkflowTransition.delete_all
  5998. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
  5999. :old_status_id => 1, :new_status_id => 1)
  6000. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
  6001. :old_status_id => 1, :new_status_id => 3)
  6002. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
  6003. :old_status_id => 1, :new_status_id => 4)
  6004. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
  6005. :old_status_id => 2, :new_status_id => 1)
  6006. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
  6007. :old_status_id => 2, :new_status_id => 3)
  6008. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2,
  6009. :old_status_id => 2, :new_status_id => 5)
  6010. @request.session[:user_id] = 2
  6011. get(:bulk_edit, :params => {:ids => [1, 2]})
  6012. assert_select 'select[name=?]', 'issue[status_id]' do
  6013. assert_select 'option[value=""]'
  6014. assert_select 'option[value="1"]'
  6015. assert_select 'option[value="3"]'
  6016. assert_select 'option', 3 # 2 statuses + "no change" option
  6017. end
  6018. end
  6019. def test_bulk_edit_should_propose_target_project_open_shared_versions
  6020. @request.session[:user_id] = 2
  6021. post(
  6022. :bulk_edit,
  6023. :params => {
  6024. :ids => [1, 2, 6],
  6025. :issue => {
  6026. :project_id => 1
  6027. }
  6028. }
  6029. )
  6030. assert_response :success
  6031. expected_versions = Project.find(1).shared_versions.open.to_a.sort
  6032. assert_select 'select[name=?]', 'issue[fixed_version_id]' do
  6033. expected_versions.each do |version|
  6034. assert_select 'option[value=?]', version.id.to_s
  6035. end
  6036. assert_select 'option[value=""]'
  6037. assert_select 'option[value="none"]'
  6038. assert_select 'option', expected_versions.size + 2
  6039. end
  6040. end
  6041. def test_bulk_edit_should_propose_target_project_categories
  6042. @request.session[:user_id] = 2
  6043. post(
  6044. :bulk_edit,
  6045. :params => {
  6046. :ids => [1, 2, 6],
  6047. :issue => {
  6048. :project_id => 1
  6049. }
  6050. }
  6051. )
  6052. assert_response :success
  6053. expected_categories = Project.find(1).issue_categories.sort
  6054. assert_select 'select[name=?]', 'issue[category_id]' do
  6055. expected_categories.each do |category|
  6056. assert_select 'option[value=?]', category.id.to_s
  6057. end
  6058. assert_select 'option[value=""]'
  6059. assert_select 'option[value="none"]'
  6060. assert_select 'option', expected_categories.size + 2
  6061. end
  6062. end
  6063. def test_bulk_edit_should_only_propose_issues_trackers_custom_fields
  6064. IssueCustomField.delete_all
  6065. field1 = IssueCustomField.generate!(:tracker_ids => [1], :is_for_all => true)
  6066. field2 = IssueCustomField.generate!(:tracker_ids => [2], :is_for_all => true)
  6067. @request.session[:user_id] = 2
  6068. issue_ids = Issue.where(:project_id => 1, :tracker_id => 1).limit(2).ids
  6069. get(
  6070. :bulk_edit,
  6071. :params => {
  6072. :ids => issue_ids
  6073. }
  6074. )
  6075. assert_response :success
  6076. assert_select 'input[name=?]', "issue[custom_field_values][#{field1.id}]"
  6077. assert_select 'input[name=?]', "issue[custom_field_values][#{field2.id}]", 0
  6078. end
  6079. def test_bulk_edit_should_propose_target_tracker_custom_fields
  6080. IssueCustomField.delete_all
  6081. field1 = IssueCustomField.generate!(:tracker_ids => [1], :is_for_all => true)
  6082. field2 = IssueCustomField.generate!(:tracker_ids => [2], :is_for_all => true)
  6083. @request.session[:user_id] = 2
  6084. issue_ids = Issue.where(:project_id => 1, :tracker_id => 1).limit(2).ids
  6085. get(
  6086. :bulk_edit,
  6087. :params => {
  6088. :ids => issue_ids,
  6089. :issue => {
  6090. :tracker_id => 2
  6091. }
  6092. }
  6093. )
  6094. assert_response :success
  6095. assert_select 'input[name=?]', "issue[custom_field_values][#{field1.id}]", 0
  6096. assert_select 'input[name=?]', "issue[custom_field_values][#{field2.id}]"
  6097. end
  6098. def test_bulk_edit_should_warn_about_custom_field_values_about_to_be_cleared
  6099. CustomField.destroy_all
  6100. cleared = IssueCustomField.generate!(:name => 'Cleared',
  6101. :tracker_ids => [2],
  6102. :is_for_all => true)
  6103. CustomValue.create!(:customized => Issue.find(2),
  6104. :custom_field => cleared,
  6105. :value => 'foo')
  6106. not_cleared = IssueCustomField.generate!(:name => 'Not cleared',
  6107. :tracker_ids => [2, 3],
  6108. :is_for_all => true)
  6109. CustomValue.create!(:customized => Issue.find(2),
  6110. :custom_field => not_cleared,
  6111. :value => 'bar')
  6112. @request.session[:user_id] = 2
  6113. get(
  6114. :bulk_edit,
  6115. :params => {
  6116. :ids => [1, 2],
  6117. :issue => {
  6118. :tracker_id => 3
  6119. }
  6120. }
  6121. )
  6122. assert_response :success
  6123. assert_select '.warning', :text => /automatic deletion of values/
  6124. assert_select '.warning span', :text => 'Cleared (1)'
  6125. assert_select '.warning span', :text => /Not cleared/, :count => 0
  6126. end
  6127. def test_bulk_update
  6128. @request.session[:user_id] = 2
  6129. # update issues priority
  6130. post(
  6131. :bulk_update,
  6132. :params => {
  6133. :ids => [1, 2],
  6134. :notes => 'Bulk editing',
  6135. :issue => {
  6136. :priority_id => 7,
  6137. :assigned_to_id => '',
  6138. :custom_field_values => {
  6139. '2' => ''
  6140. }
  6141. }
  6142. }
  6143. )
  6144. assert_response 302
  6145. # check that the issues were updated
  6146. assert_equal [7, 7], Issue.where(:id =>[1, 2]).collect {|i| i.priority.id}
  6147. issue = Issue.find(1)
  6148. journal = issue.journals.reorder('created_on DESC').first
  6149. assert_equal '125', issue.custom_value_for(2).value
  6150. assert_equal 'Bulk editing', journal.notes
  6151. assert_equal 1, journal.details.size
  6152. end
  6153. def test_bulk_update_with_group_assignee
  6154. group = Group.find(11)
  6155. project = Project.find(1)
  6156. project.members << Member.new(:principal => group, :roles => [Role.givable.first])
  6157. @request.session[:user_id] = 2
  6158. # update issues assignee
  6159. with_settings :issue_group_assignment => '1' do
  6160. post(
  6161. :bulk_update,
  6162. :params => {
  6163. :ids => [1, 2],
  6164. :notes => 'Bulk editing',
  6165. :issue => {
  6166. :priority_id => '',
  6167. :assigned_to_id => group.id,
  6168. :custom_field_values => {
  6169. '2' => ''
  6170. }
  6171. }
  6172. }
  6173. )
  6174. assert_response 302
  6175. assert_equal [group, group], Issue.where(:id => [1, 2]).collect {|i| i.assigned_to}
  6176. end
  6177. end
  6178. def test_bulk_update_on_different_projects
  6179. @request.session[:user_id] = 2
  6180. # update issues priority
  6181. post(
  6182. :bulk_update,
  6183. :params => {
  6184. :ids => [1, 2, 6],
  6185. :notes => 'Bulk editing',
  6186. :issue => {
  6187. :priority_id => 7,
  6188. :assigned_to_id => '',
  6189. :custom_field_values => {
  6190. '2' => ''
  6191. }
  6192. }
  6193. }
  6194. )
  6195. assert_response 302
  6196. # check that the issues were updated
  6197. assert_equal [7, 7, 7], Issue.find([1, 2, 6]).map(&:priority_id)
  6198. issue = Issue.find(1)
  6199. journal = issue.journals.reorder('created_on DESC').first
  6200. assert_equal '125', issue.custom_value_for(2).value
  6201. assert_equal 'Bulk editing', journal.notes
  6202. assert_equal 1, journal.details.size
  6203. end
  6204. def test_bulk_update_on_different_projects_without_rights
  6205. @request.session[:user_id] = 3
  6206. user = User.find(3)
  6207. action = {:controller => "issues", :action => "bulk_update"}
  6208. assert user.allowed_to?(action, Issue.find(1).project)
  6209. assert ! user.allowed_to?(action, Issue.find(6).project)
  6210. post(
  6211. :bulk_update,
  6212. :params => {
  6213. :ids => [1, 6],
  6214. :notes => 'Bulk should fail',
  6215. :issue => {
  6216. :priority_id => 7,
  6217. :assigned_to_id => '',
  6218. :custom_field_values => {
  6219. '2' => ''
  6220. }
  6221. }
  6222. }
  6223. )
  6224. assert_response 403
  6225. assert_not_equal "Bulk should fail", Journal.last.notes
  6226. end
  6227. def test_bulk_update_should_send_a_notification
  6228. @request.session[:user_id] = 2
  6229. ActionMailer::Base.deliveries.clear
  6230. with_settings :notified_events => %w(issue_updated) do
  6231. post(
  6232. :bulk_update,
  6233. :params => {
  6234. :ids => [1, 2],
  6235. :notes => 'Bulk editing',
  6236. :issue => {
  6237. :priority_id => 7,
  6238. :assigned_to_id => '',
  6239. :custom_field_values => {'2' => ''}
  6240. }
  6241. }
  6242. )
  6243. assert_response 302
  6244. # 4 emails for 2 members and 2 issues
  6245. # 1 email for a watcher of issue #2
  6246. assert_equal 5, ActionMailer::Base.deliveries.size
  6247. end
  6248. end
  6249. def test_bulk_update_project
  6250. @request.session[:user_id] = 2
  6251. post(
  6252. :bulk_update,
  6253. :params => {
  6254. :ids => [1, 2],
  6255. :issue => {
  6256. :project_id => '2'
  6257. }
  6258. }
  6259. )
  6260. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  6261. # Issues moved to project 2
  6262. assert_equal 2, Issue.find(1).project_id
  6263. assert_equal 2, Issue.find(2).project_id
  6264. # No tracker change
  6265. assert_equal 1, Issue.find(1).tracker_id
  6266. assert_equal 2, Issue.find(2).tracker_id
  6267. end
  6268. def test_bulk_update_project_on_single_issue_should_follow_when_needed
  6269. @request.session[:user_id] = 2
  6270. post(
  6271. :bulk_update,
  6272. :params => {
  6273. :id => 1,
  6274. :issue => {
  6275. :project_id => '2'
  6276. },
  6277. :follow => '1'
  6278. }
  6279. )
  6280. assert_redirected_to '/issues/1'
  6281. end
  6282. def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
  6283. @request.session[:user_id] = 2
  6284. post(
  6285. :bulk_update,
  6286. :params => {
  6287. :id => [1, 2],
  6288. :issue => {
  6289. :project_id => '2'
  6290. },
  6291. :follow => '1'
  6292. }
  6293. )
  6294. assert_redirected_to '/projects/onlinestore/issues'
  6295. end
  6296. def test_bulk_update_tracker
  6297. @request.session[:user_id] = 2
  6298. post(
  6299. :bulk_update, :params => {
  6300. :ids => [1, 2],
  6301. :issue => {
  6302. :tracker_id => '2'
  6303. }
  6304. }
  6305. )
  6306. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  6307. assert_equal 2, Issue.find(1).tracker_id
  6308. assert_equal 2, Issue.find(2).tracker_id
  6309. end
  6310. def test_bulk_update_status
  6311. @request.session[:user_id] = 2
  6312. # update issues priority
  6313. post(
  6314. :bulk_update,
  6315. :params => {
  6316. :ids => [1, 2],
  6317. :notes => 'Bulk editing status',
  6318. :issue => {
  6319. :priority_id => '',
  6320. :assigned_to_id => '',
  6321. :status_id => '5'
  6322. }
  6323. }
  6324. )
  6325. assert_response 302
  6326. issue = Issue.find(1)
  6327. assert issue.closed?
  6328. end
  6329. def test_bulk_update_priority
  6330. @request.session[:user_id] = 2
  6331. post(
  6332. :bulk_update,
  6333. :params => {
  6334. :ids => [1, 2],
  6335. :issue => {
  6336. :priority_id => 6
  6337. }
  6338. }
  6339. )
  6340. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  6341. assert_equal 6, Issue.find(1).priority_id
  6342. assert_equal 6, Issue.find(2).priority_id
  6343. end
  6344. def test_bulk_update_with_notes
  6345. @request.session[:user_id] = 2
  6346. post(
  6347. :bulk_update,
  6348. :params => {
  6349. :ids => [1, 2],
  6350. :notes => 'Moving two issues'
  6351. }
  6352. )
  6353. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  6354. assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
  6355. assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
  6356. assert_equal false, Issue.find(1).journals.sort_by(&:id).last.private_notes
  6357. assert_equal false, Issue.find(2).journals.sort_by(&:id).last.private_notes
  6358. end
  6359. def test_bulk_update_with_private_notes
  6360. @request.session[:user_id] = 2
  6361. post(
  6362. :bulk_update,
  6363. :params => {
  6364. :ids => [1, 2],
  6365. :notes => 'Moving two issues',
  6366. :issue => {:private_notes => 'true'}
  6367. }
  6368. )
  6369. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  6370. assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
  6371. assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
  6372. assert_equal true, Issue.find(1).journals.sort_by(&:id).last.private_notes
  6373. assert_equal true, Issue.find(2).journals.sort_by(&:id).last.private_notes
  6374. end
  6375. def test_bulk_update_parent_id
  6376. IssueRelation.delete_all
  6377. @request.session[:user_id] = 2
  6378. post(
  6379. :bulk_update,
  6380. :params => {
  6381. :ids => [1, 3],
  6382. :notes => 'Bulk editing parent',
  6383. :issue => {
  6384. :priority_id => '',
  6385. :assigned_to_id => '',
  6386. :status_id => '',
  6387. :parent_issue_id => '2'
  6388. }
  6389. }
  6390. )
  6391. assert_response 302
  6392. parent = Issue.find(2)
  6393. assert_equal parent.id, Issue.find(1).parent_id
  6394. assert_equal parent.id, Issue.find(3).parent_id
  6395. assert_equal [1, 3], parent.children.collect(&:id).sort
  6396. end
  6397. def test_bulk_update_estimated_hours
  6398. @request.session[:user_id] = 2
  6399. post(
  6400. :bulk_update,
  6401. :params => {
  6402. :ids => [1, 2],
  6403. :issue => {
  6404. :estimated_hours => 4.25
  6405. }
  6406. }
  6407. )
  6408. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  6409. assert_equal 4.25, Issue.find(1).estimated_hours
  6410. assert_equal 4.25, Issue.find(2).estimated_hours
  6411. end
  6412. def test_bulk_update_custom_field
  6413. @request.session[:user_id] = 2
  6414. # update issues priority
  6415. post(
  6416. :bulk_update,
  6417. :params => {
  6418. :ids => [1, 2],
  6419. :notes => 'Bulk editing custom field',
  6420. :issue => {
  6421. :priority_id => '',
  6422. :assigned_to_id => '',
  6423. :custom_field_values => {
  6424. '2' => '777'
  6425. }
  6426. }
  6427. }
  6428. )
  6429. assert_response 302
  6430. issue = Issue.find(1)
  6431. journal = issue.journals.reorder('created_on DESC').first
  6432. assert_equal '777', issue.custom_value_for(2).value
  6433. assert_equal 1, journal.details.size
  6434. assert_equal '125', journal.details.first.old_value
  6435. assert_equal '777', journal.details.first.value
  6436. end
  6437. def test_bulk_update_custom_field_to_blank
  6438. @request.session[:user_id] = 2
  6439. post(
  6440. :bulk_update,
  6441. :params => {
  6442. :ids => [1, 3],
  6443. :notes => 'Bulk editing custom field',
  6444. :issue => {
  6445. :priority_id => '',
  6446. :assigned_to_id => '',
  6447. :custom_field_values => {
  6448. '1' => '__none__'
  6449. }
  6450. }
  6451. }
  6452. )
  6453. assert_response 302
  6454. assert_equal '', Issue.find(1).custom_field_value(1)
  6455. assert_equal '', Issue.find(3).custom_field_value(1)
  6456. end
  6457. def test_bulk_update_multi_custom_field
  6458. field = CustomField.find(1)
  6459. field.update_attribute :multiple, true
  6460. @request.session[:user_id] = 2
  6461. post(
  6462. :bulk_update,
  6463. :params => {
  6464. :ids => [1, 2, 3],
  6465. :notes => 'Bulk editing multi custom field',
  6466. :issue => {
  6467. :priority_id => '',
  6468. :assigned_to_id => '',
  6469. :custom_field_values => {
  6470. '1' => ['MySQL', 'Oracle']
  6471. }
  6472. }
  6473. }
  6474. )
  6475. assert_response 302
  6476. assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
  6477. assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
  6478. # the custom field is not associated with the issue tracker
  6479. assert_nil Issue.find(2).custom_field_value(1)
  6480. end
  6481. def test_bulk_update_multi_custom_field_to_blank
  6482. field = CustomField.find(1)
  6483. field.update_attribute :multiple, true
  6484. @request.session[:user_id] = 2
  6485. post(
  6486. :bulk_update,
  6487. :params => {
  6488. :ids => [1, 3],
  6489. :notes => 'Bulk editing multi custom field',
  6490. :issue => {
  6491. :priority_id => '',
  6492. :assigned_to_id => '',
  6493. :custom_field_values => {
  6494. '1' => ['__none__']
  6495. }
  6496. }
  6497. }
  6498. )
  6499. assert_response 302
  6500. assert_equal [''], Issue.find(1).custom_field_value(1)
  6501. assert_equal [''], Issue.find(3).custom_field_value(1)
  6502. end
  6503. def test_bulk_update_unassign
  6504. assert_not_nil Issue.find(2).assigned_to
  6505. @request.session[:user_id] = 2
  6506. # unassign issues
  6507. post(
  6508. :bulk_update,
  6509. :params => {
  6510. :ids => [1, 2],
  6511. :notes => 'Bulk unassigning',
  6512. :issue => {
  6513. :assigned_to_id => 'none'
  6514. }
  6515. }
  6516. )
  6517. assert_response 302
  6518. # check that the issues were updated
  6519. assert_nil Issue.find(2).assigned_to
  6520. end
  6521. def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
  6522. @request.session[:user_id] = 2
  6523. post(
  6524. :bulk_update,
  6525. :params => {
  6526. :ids => [1, 2],
  6527. :issue => {
  6528. :fixed_version_id => 4
  6529. }
  6530. }
  6531. )
  6532. assert_response :redirect
  6533. issues = Issue.find([1, 2])
  6534. issues.each do |issue|
  6535. assert_equal 4, issue.fixed_version_id
  6536. assert_not_equal issue.project_id, issue.fixed_version.project_id
  6537. end
  6538. end
  6539. def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
  6540. @request.session[:user_id] = 2
  6541. post(
  6542. :bulk_update,
  6543. :params => {
  6544. :ids => [1, 2],
  6545. :back_url => '/issues'
  6546. }
  6547. )
  6548. assert_response :redirect
  6549. assert_redirected_to '/issues'
  6550. end
  6551. def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
  6552. @request.session[:user_id] = 2
  6553. post(
  6554. :bulk_update,
  6555. :params => {
  6556. :ids => [1, 2],
  6557. :back_url => 'http://google.com'
  6558. }
  6559. )
  6560. assert_response :redirect
  6561. assert_redirected_to(
  6562. :controller => 'issues', :action => 'index',
  6563. :project_id => Project.find(1).identifier
  6564. )
  6565. end
  6566. def test_bulk_update_with_all_failures_should_show_errors
  6567. @request.session[:user_id] = 2
  6568. post(
  6569. :bulk_update,
  6570. :params => {
  6571. :ids => [1, 2],
  6572. :issue => {
  6573. :start_date => 'foo'
  6574. }
  6575. }
  6576. )
  6577. assert_response :success
  6578. assert_select '#errorExplanation span', :text => 'Failed to save 2 issue(s) on 2 selected: #1, #2.'
  6579. assert_select '#errorExplanation ul li', :text => 'Start date is not a valid date: #1, #2'
  6580. end
  6581. def test_bulk_update_with_some_failures_should_show_errors
  6582. issue1 = Issue.generate!(:start_date => '2013-05-12')
  6583. issue2 = Issue.generate!(:start_date => '2013-05-15')
  6584. issue3 = Issue.generate!
  6585. @request.session[:user_id] = 2
  6586. post(
  6587. :bulk_update,
  6588. :params => {
  6589. :ids => [issue1.id, issue2.id, issue3.id],
  6590. :issue => {
  6591. :due_date => '2013-05-01'
  6592. }
  6593. }
  6594. )
  6595. assert_response :success
  6596. assert_select '#errorExplanation span',
  6597. :text => "Failed to save 2 issue(s) on 3 selected: ##{issue1.id}, ##{issue2.id}."
  6598. assert_select '#errorExplanation ul li',
  6599. :text => "Due date must be greater than start date: ##{issue1.id}, ##{issue2.id}"
  6600. assert_select '#bulk-selection li', 2
  6601. end
  6602. def test_bulk_update_with_failure_should_preserved_form_values
  6603. @request.session[:user_id] = 2
  6604. post(
  6605. :bulk_update,
  6606. :params => {
  6607. :ids => [1, 2],
  6608. :issue => {
  6609. :tracker_id => '2',
  6610. :start_date => 'foo'
  6611. }
  6612. }
  6613. )
  6614. assert_response :success
  6615. assert_select 'select[name=?]', 'issue[tracker_id]' do
  6616. assert_select 'option[value="2"][selected=selected]'
  6617. end
  6618. assert_select 'input[name=?][value=?]', 'issue[start_date]', 'foo'
  6619. end
  6620. def test_get_bulk_copy
  6621. assert_not Issue.find(1).attachments.any?
  6622. assert Issue.find(2).attachments.any?
  6623. assert Issue.find(3).attachments.any?
  6624. @request.session[:user_id] = 2
  6625. get(
  6626. :bulk_edit,
  6627. :params => {
  6628. :ids => [1, 2, 3],
  6629. :copy => '1'
  6630. }
  6631. )
  6632. assert_response :success
  6633. assert_select '#bulk-selection li', 3
  6634. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  6635. assert_select 'select[name=?]', 'issue[project_id]' do
  6636. assert_select 'option[value=""]'
  6637. end
  6638. assert_select 'input[name=copy_attachments]'
  6639. end
  6640. end
  6641. test "bulk copy should show follow button when project is selected" do
  6642. @request.session[:user_id] = 2
  6643. post(
  6644. :bulk_edit,
  6645. :params => {
  6646. :ids => [1, 3],
  6647. :issue => {
  6648. :project_id => 2,
  6649. },
  6650. :copy => '1',
  6651. }
  6652. )
  6653. assert_response :success
  6654. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  6655. assert_select 'input[type=submit]', 2 do
  6656. assert_select '[name=?]', 'commit', 1
  6657. assert_select '[name=?]', 'follow', 1
  6658. end
  6659. end
  6660. end
  6661. def test_get_bulk_copy_without_add_issues_permission_should_not_propose_current_project_as_target
  6662. user = setup_user_with_copy_but_not_add_permission
  6663. @request.session[:user_id] = user.id
  6664. get(
  6665. :bulk_edit,
  6666. :params => {
  6667. :ids => [1, 2, 3],
  6668. :copy => '1'
  6669. }
  6670. )
  6671. assert_response :success
  6672. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  6673. assert_select 'select[name=?]', 'issue[project_id]' do
  6674. assert_select 'option[value=""]', 0
  6675. assert_select 'option[value="2"]'
  6676. end
  6677. end
  6678. end
  6679. def test_bulk_copy_to_another_project
  6680. @request.session[:user_id] = 2
  6681. issue_ids = [1, 2]
  6682. assert_difference 'Issue.count', issue_ids.size do
  6683. assert_no_difference 'Project.find(1).issues.count' do
  6684. post(
  6685. :bulk_update,
  6686. :params => {
  6687. :ids => issue_ids,
  6688. :issue => {
  6689. :project_id => '2'
  6690. },
  6691. :copy => '1'
  6692. }
  6693. )
  6694. end
  6695. end
  6696. assert_redirected_to '/projects/ecookbook/issues'
  6697. copies = Issue.order('id DESC').limit(issue_ids.size)
  6698. copies.each do |copy|
  6699. assert_equal 2, copy.project_id
  6700. end
  6701. end
  6702. def test_bulk_copy_without_add_issues_permission_should_be_allowed_on_project_with_permission
  6703. user = setup_user_with_copy_but_not_add_permission
  6704. @request.session[:user_id] = user.id
  6705. assert_difference 'Issue.count', 3 do
  6706. post(
  6707. :bulk_update,
  6708. :params => {
  6709. :ids => [1, 2, 3],
  6710. :issue => {
  6711. :project_id => '2'
  6712. },
  6713. :copy => '1'
  6714. }
  6715. )
  6716. assert_response 302
  6717. end
  6718. end
  6719. def test_bulk_copy_on_same_project_without_add_issues_permission_should_be_denied
  6720. user = setup_user_with_copy_but_not_add_permission
  6721. @request.session[:user_id] = user.id
  6722. post(
  6723. :bulk_update,
  6724. :params => {
  6725. :ids => [1, 2, 3],
  6726. :issue => {
  6727. :project_id => ''
  6728. },
  6729. :copy => '1'
  6730. }
  6731. )
  6732. assert_response 403
  6733. end
  6734. def test_bulk_copy_on_different_project_without_add_issues_permission_should_be_denied
  6735. user = setup_user_with_copy_but_not_add_permission
  6736. @request.session[:user_id] = user.id
  6737. post(
  6738. :bulk_update,
  6739. :params => {
  6740. :ids => [1, 2, 3],
  6741. :issue => {
  6742. :project_id => '1'
  6743. },
  6744. :copy => '1'
  6745. }
  6746. )
  6747. assert_response 403
  6748. end
  6749. def test_bulk_copy_should_allow_not_changing_the_issue_attributes
  6750. @request.session[:user_id] = 2
  6751. issues = [
  6752. Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
  6753. :priority_id => 2, :subject => 'issue 1', :author_id => 1,
  6754. :assigned_to_id => nil),
  6755. Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2,
  6756. :priority_id => 1, :subject => 'issue 2', :author_id => 2,
  6757. :assigned_to_id => 2)
  6758. ]
  6759. assert_difference 'Issue.count', issues.size do
  6760. post(
  6761. :bulk_update,
  6762. :params => {
  6763. :ids => issues.map(&:id),
  6764. :copy => '1',
  6765. :issue => {
  6766. :project_id => '',
  6767. :tracker_id => '',
  6768. :assigned_to_id => '',
  6769. :status_id => '',
  6770. :start_date => '',
  6771. :due_date => ''
  6772. }
  6773. }
  6774. )
  6775. end
  6776. copies = Issue.order('id DESC').limit(issues.size)
  6777. issues.each do |orig|
  6778. copy = copies.detect {|c| c.subject == orig.subject}
  6779. assert_not_nil copy
  6780. assert_equal orig.project_id, copy.project_id
  6781. assert_equal orig.tracker_id, copy.tracker_id
  6782. assert_equal 1, copy.status_id
  6783. if orig.assigned_to_id
  6784. assert_equal orig.assigned_to_id, copy.assigned_to_id
  6785. else
  6786. assert_nil copy.assigned_to_id
  6787. end
  6788. assert_equal orig.priority_id, copy.priority_id
  6789. end
  6790. end
  6791. def test_bulk_copy_should_allow_changing_the_issue_attributes
  6792. # Fixes random test failure with Mysql
  6793. # where Issue.where(:project_id => 2).limit(2).order('id desc')
  6794. # doesn't return the expected results
  6795. Issue.where("project_id=2").delete_all
  6796. @request.session[:user_id] = 2
  6797. assert_difference 'Issue.count', 2 do
  6798. assert_no_difference 'Project.find(1).issues.count' do
  6799. post(
  6800. :bulk_update,
  6801. :params => {
  6802. :ids => [1, 2],
  6803. :copy => '1',
  6804. :issue => {
  6805. :project_id => '2',
  6806. :tracker_id => '',
  6807. :assigned_to_id => '2',
  6808. :status_id => '1',
  6809. :start_date => '2009-12-01',
  6810. :due_date => '2009-12-31'
  6811. }
  6812. }
  6813. )
  6814. end
  6815. end
  6816. copied_issues = Issue.where(:project_id => 2).limit(2).order('id desc').to_a
  6817. assert_equal 2, copied_issues.size
  6818. copied_issues.each do |issue|
  6819. assert_equal 2, issue.project_id, "Project is incorrect"
  6820. assert_equal 2, issue.assigned_to_id, "Assigned to is incorrect"
  6821. assert_equal 1, issue.status_id, "Status is incorrect"
  6822. assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
  6823. assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
  6824. end
  6825. end
  6826. def test_bulk_copy_should_allow_adding_a_note
  6827. @request.session[:user_id] = 2
  6828. assert_difference 'Issue.count', 1 do
  6829. post(
  6830. :bulk_update,
  6831. :params => {
  6832. :ids => [1],
  6833. :copy => '1',
  6834. :notes => 'Copying one issue',
  6835. :issue => {
  6836. :project_id => '',
  6837. :tracker_id => '',
  6838. :status_id => '3',
  6839. :start_date => '2009-12-01',
  6840. :due_date => '2009-12-31'
  6841. }
  6842. }
  6843. )
  6844. end
  6845. issue = Issue.order('id DESC').first
  6846. assert_equal 1, issue.journals.size
  6847. journal = issue.journals.first
  6848. assert_equal 'Copying one issue', journal.notes
  6849. end
  6850. def test_bulk_copy_should_allow_not_copying_the_attachments
  6851. attachment_count = Issue.find(3).attachments.size
  6852. assert attachment_count > 0
  6853. @request.session[:user_id] = 2
  6854. assert_difference 'Issue.count', 1 do
  6855. assert_no_difference 'Attachment.count' do
  6856. post(
  6857. :bulk_update,
  6858. :params => {
  6859. :ids => [3],
  6860. :copy => '1',
  6861. :copy_attachments => '0',
  6862. :issue => {
  6863. :project_id => ''
  6864. }
  6865. }
  6866. )
  6867. end
  6868. end
  6869. end
  6870. def test_bulk_copy_should_allow_copying_the_attachments
  6871. attachment_count = Issue.find(3).attachments.size
  6872. assert attachment_count > 0
  6873. @request.session[:user_id] = 2
  6874. assert_difference 'Issue.count', 1 do
  6875. assert_difference 'Attachment.count', attachment_count do
  6876. post(
  6877. :bulk_update,
  6878. :params => {
  6879. :ids => [3],
  6880. :copy => '1',
  6881. :copy_attachments => '1',
  6882. :issue => {
  6883. :project_id => ''
  6884. }
  6885. }
  6886. )
  6887. end
  6888. end
  6889. end
  6890. def test_bulk_copy_should_add_relations_with_copied_issues
  6891. @request.session[:user_id] = 2
  6892. assert_difference 'Issue.count', 2 do
  6893. assert_difference 'IssueRelation.count', 2 do
  6894. post(
  6895. :bulk_update,
  6896. :params => {
  6897. :ids => [1, 3],
  6898. :copy => '1',
  6899. :link_copy => '1',
  6900. :issue => {
  6901. :project_id => '1'
  6902. }
  6903. }
  6904. )
  6905. end
  6906. end
  6907. end
  6908. def test_bulk_copy_should_allow_not_copying_the_subtasks
  6909. issue = Issue.generate_with_descendants!
  6910. @request.session[:user_id] = 2
  6911. assert_difference 'Issue.count', 1 do
  6912. post(
  6913. :bulk_update,
  6914. :params => {
  6915. :ids => [issue.id],
  6916. :copy => '1',
  6917. :copy_subtasks => '0',
  6918. :issue => {
  6919. :project_id => ''
  6920. }
  6921. }
  6922. )
  6923. end
  6924. end
  6925. test "bulk copy should allow copying the subtasks" do
  6926. issue = Issue.generate_with_descendants!
  6927. count = issue.descendants.count
  6928. @request.session[:user_id] = 2
  6929. assert_difference 'Issue.count', count + 1 do
  6930. post(
  6931. :bulk_update,
  6932. :params => {
  6933. :ids => [issue.id],
  6934. :copy => '1',
  6935. :copy_subtasks => '1',
  6936. :issue => {
  6937. :project_id => ''
  6938. }
  6939. }
  6940. )
  6941. end
  6942. copy = Issue.where(:parent_id => nil).order("id DESC").first
  6943. assert_equal count, copy.descendants.count
  6944. end
  6945. test "issue bulk copy copy watcher" do
  6946. issue = Issue.find(1)
  6947. Watcher.create!(:watchable => issue, :user => User.find(3))
  6948. Watcher.create!(:watchable => issue, :user => Group.find(10))
  6949. @request.session[:user_id] = 2
  6950. assert_difference 'Issue.count' do
  6951. post(
  6952. :bulk_update,
  6953. :params => {
  6954. :ids => [1],
  6955. :copy => '1',
  6956. :copy_watchers => '1',
  6957. :issue => {
  6958. :project_id => ''
  6959. }
  6960. }
  6961. )
  6962. end
  6963. copy = Issue.order(:id => :desc).first
  6964. assert_equal 2, copy.watchers.count
  6965. assert_equal [3, 10], copy.watcher_user_ids
  6966. end
  6967. def test_bulk_copy_should_not_copy_selected_subtasks_twice
  6968. issue = Issue.generate_with_descendants!
  6969. count = issue.descendants.count
  6970. @request.session[:user_id] = 2
  6971. assert_difference 'Issue.count', count + 1 do
  6972. post(
  6973. :bulk_update,
  6974. :params => {
  6975. :ids => issue.self_and_descendants.map(&:id),
  6976. :copy => '1',
  6977. :copy_subtasks => '1',
  6978. :issue => {
  6979. :project_id => ''
  6980. }
  6981. }
  6982. )
  6983. end
  6984. copy = Issue.where(:parent_id => nil).order("id DESC").first
  6985. assert_equal count, copy.descendants.count
  6986. end
  6987. def test_bulk_copy_to_another_project_should_follow_when_needed
  6988. @request.session[:user_id] = 2
  6989. post(
  6990. :bulk_update,
  6991. :params => {
  6992. :ids => [1],
  6993. :copy => '1',
  6994. :issue => {
  6995. :project_id => 2
  6996. },
  6997. :follow => '1'
  6998. }
  6999. )
  7000. issue = Issue.order('id DESC').first
  7001. assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
  7002. end
  7003. def test_bulk_copy_with_all_failures_should_display_errors
  7004. @request.session[:user_id] = 2
  7005. post(
  7006. :bulk_update,
  7007. :params => {
  7008. :ids => [1, 2],
  7009. :copy => '1',
  7010. :issue => {
  7011. :start_date => 'foo'
  7012. }
  7013. }
  7014. )
  7015. assert_response :success
  7016. end
  7017. def test_destroy_issue_with_no_time_entries_should_delete_the_issues
  7018. set_tmp_attachments_directory
  7019. assert_nil TimeEntry.find_by_issue_id(2)
  7020. @request.session[:user_id] = 2
  7021. assert_difference 'Issue.count', -1 do
  7022. delete(:destroy, :params => {:id => 2})
  7023. end
  7024. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  7025. assert_equal 'Successful deletion.', flash[:notice]
  7026. assert_nil Issue.find_by_id(2)
  7027. end
  7028. def test_destroy_issues_with_time_entries_should_show_the_reassign_form
  7029. set_tmp_attachments_directory
  7030. @request.session[:user_id] = 2
  7031. with_settings :timelog_required_fields => [] do
  7032. assert_no_difference 'Issue.count' do
  7033. delete(
  7034. :destroy,
  7035. :params => {
  7036. :ids => [1, 3]
  7037. }
  7038. )
  7039. end
  7040. end
  7041. assert_response :success
  7042. assert_select 'form' do
  7043. assert_select 'input[name=_method][value=delete]'
  7044. assert_select 'input[name=todo][value=destroy]'
  7045. assert_select 'input[name=todo][value=nullify]'
  7046. assert_select 'input[name=todo][value=reassign]'
  7047. end
  7048. end
  7049. def test_destroy_issues_with_time_entries_should_not_show_the_nullify_option_when_issue_is_required_for_time_entries
  7050. set_tmp_attachments_directory
  7051. with_settings :timelog_required_fields => ['issue_id'] do
  7052. @request.session[:user_id] = 2
  7053. assert_no_difference 'Issue.count' do
  7054. delete(
  7055. :destroy,
  7056. :params => {
  7057. :ids => [1, 3]
  7058. }
  7059. )
  7060. end
  7061. assert_response :success
  7062. assert_select 'form' do
  7063. assert_select 'input[name=_method][value=delete]'
  7064. assert_select 'input[name=todo][value=destroy]'
  7065. assert_select 'input[name=todo][value=nullify]', 0
  7066. assert_select 'input[name=todo][value=reassign]'
  7067. end
  7068. end
  7069. end
  7070. def test_destroy_issues_with_time_entries_should_show_hours_on_issues_and_descendants
  7071. parent = Issue.generate_with_child!
  7072. TimeEntry.generate!(:issue => parent)
  7073. TimeEntry.generate!(:issue => parent.children.first)
  7074. leaf = Issue.generate!
  7075. TimeEntry.generate!(:issue => leaf)
  7076. @request.session[:user_id] = 2
  7077. delete(
  7078. :destroy,
  7079. :params => {
  7080. :ids => [parent.id, leaf.id]
  7081. }
  7082. )
  7083. assert_response :success
  7084. assert_select 'p', :text => /3\.00 hours were reported/
  7085. end
  7086. def test_destroy_issues_and_destroy_time_entries
  7087. set_tmp_attachments_directory
  7088. @request.session[:user_id] = 2
  7089. assert_difference 'Issue.count', -2 do
  7090. assert_difference 'TimeEntry.count', -3 do
  7091. delete(
  7092. :destroy,
  7093. :params => {
  7094. :ids => [1, 3],
  7095. :todo => 'destroy'
  7096. }
  7097. )
  7098. end
  7099. end
  7100. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  7101. assert_equal 'Successful deletion.', flash[:notice]
  7102. assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
  7103. assert_nil TimeEntry.find_by_id([1, 2])
  7104. end
  7105. def test_destroy_issues_and_assign_time_entries_to_project
  7106. set_tmp_attachments_directory
  7107. @request.session[:user_id] = 2
  7108. with_settings :timelog_required_fields => [] do
  7109. assert_difference 'Issue.count', -2 do
  7110. assert_no_difference 'TimeEntry.count' do
  7111. delete(
  7112. :destroy,
  7113. :params => {
  7114. :ids => [1, 3],
  7115. :todo => 'nullify'
  7116. }
  7117. )
  7118. end
  7119. end
  7120. end
  7121. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  7122. assert_equal 'Successful deletion.', flash[:notice]
  7123. assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
  7124. assert_nil TimeEntry.find(1).issue_id
  7125. assert_nil TimeEntry.find(2).issue_id
  7126. end
  7127. def test_destroy_issues_and_reassign_time_entries_to_another_issue
  7128. set_tmp_attachments_directory
  7129. @request.session[:user_id] = 2
  7130. assert_difference 'Issue.count', -2 do
  7131. assert_no_difference 'TimeEntry.count' do
  7132. delete(
  7133. :destroy,
  7134. :params => {
  7135. :ids => [1, 3],
  7136. :todo => 'reassign',
  7137. :reassign_to_id => 2
  7138. }
  7139. )
  7140. end
  7141. end
  7142. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  7143. assert_equal 'Successful deletion.', flash[:notice]
  7144. assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
  7145. assert_equal 2, TimeEntry.find(1).issue_id
  7146. assert_equal 2, TimeEntry.find(2).issue_id
  7147. end
  7148. def test_destroy_issues_with_time_entries_should_reassign_time_entries_of_issues_and_descendants
  7149. parent = Issue.generate_with_child!
  7150. TimeEntry.generate!(:issue => parent)
  7151. TimeEntry.generate!(:issue => parent.children.first)
  7152. leaf = Issue.generate!
  7153. TimeEntry.generate!(:issue => leaf)
  7154. target = Issue.generate!
  7155. @request.session[:user_id] = 2
  7156. assert_difference 'Issue.count', -3 do
  7157. assert_no_difference 'TimeEntry.count' do
  7158. delete(
  7159. :destroy,
  7160. :params => {
  7161. :ids => [parent.id, leaf.id],
  7162. :todo => 'reassign',
  7163. :reassign_to_id => target.id
  7164. }
  7165. )
  7166. assert_response 302
  7167. assert_equal 'Successful deletion.', flash[:notice]
  7168. end
  7169. end
  7170. assert_equal 3, target.time_entries.count
  7171. end
  7172. def test_destroy_issues_and_reassign_time_entries_to_an_invalid_issue_should_fail
  7173. set_tmp_attachments_directory
  7174. @request.session[:user_id] = 2
  7175. assert_no_difference 'Issue.count' do
  7176. assert_no_difference 'TimeEntry.count' do
  7177. # try to reassign time to an issue of another project
  7178. delete(
  7179. :destroy,
  7180. :params => {
  7181. :ids => [1, 3],
  7182. :todo => 'reassign',
  7183. :reassign_to_id => 4
  7184. }
  7185. )
  7186. end
  7187. end
  7188. assert_response :success
  7189. end
  7190. def test_destroy_issues_and_reassign_time_entries_to_an_issue_to_delete_should_fail
  7191. set_tmp_attachments_directory
  7192. @request.session[:user_id] = 2
  7193. assert_no_difference 'Issue.count' do
  7194. assert_no_difference 'TimeEntry.count' do
  7195. delete(
  7196. :destroy,
  7197. :params => {
  7198. :ids => [1, 3],
  7199. :todo => 'reassign',
  7200. :reassign_to_id => 3
  7201. }
  7202. )
  7203. end
  7204. end
  7205. assert_response :success
  7206. assert_select '#flash_error', :text => I18n.t(:error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted)
  7207. end
  7208. def test_destroy_issues_and_nullify_time_entries_should_fail_when_issue_is_required_for_time_entries
  7209. set_tmp_attachments_directory
  7210. @request.session[:user_id] = 2
  7211. with_settings :timelog_required_fields => ['issue_id'] do
  7212. assert_no_difference 'Issue.count' do
  7213. assert_no_difference 'TimeEntry.count' do
  7214. delete(
  7215. :destroy,
  7216. :params => {
  7217. :ids => [1, 3],
  7218. :todo => 'nullify'
  7219. }
  7220. )
  7221. end
  7222. end
  7223. end
  7224. assert_response :success
  7225. assert_select '#flash_error', :text => 'Issue cannot be blank'
  7226. end
  7227. def test_destroy_issues_from_different_projects
  7228. set_tmp_attachments_directory
  7229. @request.session[:user_id] = 2
  7230. assert_difference 'Issue.count', -3 do
  7231. delete(
  7232. :destroy,
  7233. :params => {
  7234. :ids => [1, 2, 6],
  7235. :todo => 'destroy'
  7236. }
  7237. )
  7238. end
  7239. assert_redirected_to :controller => 'issues', :action => 'index'
  7240. assert_equal 'Successful deletion.', flash[:notice]
  7241. assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
  7242. end
  7243. def test_destroy_parent_and_child_issues
  7244. parent = Issue.create!(:project_id => 1, :author_id => 1,
  7245. :tracker_id => 1, :subject => 'Parent Issue')
  7246. child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1,
  7247. :subject => 'Child Issue', :parent_issue_id => parent.id)
  7248. assert child.is_descendant_of?(parent.reload)
  7249. @request.session[:user_id] = 2
  7250. assert_difference 'Issue.count', -2 do
  7251. delete(
  7252. :destroy,
  7253. :params => {
  7254. :ids => [parent.id, child.id],
  7255. :todo => 'destroy'
  7256. }
  7257. )
  7258. end
  7259. assert_response 302
  7260. assert_equal 'Successful deletion.', flash[:notice]
  7261. end
  7262. def test_destroy_invalid_should_respond_with_404
  7263. @request.session[:user_id] = 2
  7264. assert_no_difference 'Issue.count' do
  7265. delete(:destroy, :params => {:id => 999})
  7266. end
  7267. assert_response 404
  7268. end
  7269. def test_destroy_with_permission_on_tracker_should_be_allowed
  7270. role = Role.find(1)
  7271. role.set_permission_trackers :delete_issues, [1]
  7272. role.save!
  7273. issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
  7274. @request.session[:user_id] = 2
  7275. assert_difference 'Issue.count', -1 do
  7276. delete(:destroy, :params => {:id => issue.id})
  7277. end
  7278. assert_response 302
  7279. assert_equal 'Successful deletion.', flash[:notice]
  7280. end
  7281. def test_destroy_without_permission_on_tracker_should_be_denied
  7282. role = Role.find(1)
  7283. role.set_permission_trackers :delete_issues, [2]
  7284. role.save!
  7285. issue = Issue.generate!(:project_id => 1, :tracker_id => 1)
  7286. @request.session[:user_id] = 2
  7287. assert_no_difference 'Issue.count' do
  7288. delete(:destroy, :params => {:id => issue.id})
  7289. end
  7290. assert_response 403
  7291. end
  7292. def test_default_search_scope
  7293. get :index
  7294. assert_select 'div#quick-search form' do
  7295. assert_select 'input[name=issues][value="1"][type=hidden]'
  7296. end
  7297. end
  7298. def setup_user_with_copy_but_not_add_permission
  7299. Role.all.each {|r| r.remove_permission! :add_issues}
  7300. Role.find_by_name('Manager').add_permission! :add_issues
  7301. user = User.generate!
  7302. User.add_to_project(user, Project.find(1), Role.find_by_name('Developer'))
  7303. User.add_to_project(user, Project.find(2), Role.find_by_name('Manager'))
  7304. user
  7305. end
  7306. def test_cancel_edit_link_for_issue_show_action_should_have_onclick_action
  7307. @request.session[:user_id] = 1
  7308. get(:show, :params => {:id => 1})
  7309. assert_response :success
  7310. assert_select 'a[href=?][onclick=?]', "/issues/1", "$('#update').hide(); return false;", :text => 'Cancel'
  7311. end
  7312. def test_cancel_edit_link_for_issue_edit_action_should_not_have_onclick_action
  7313. @request.session[:user_id] = 1
  7314. get(:edit, :params => {:id => 1})
  7315. assert_response :success
  7316. assert_select 'a[href=?][onclick=?]', "/issues/1", "", :text => 'Cancel'
  7317. end
  7318. def test_show_should_display_author_gravatar_only_when_not_assigned
  7319. issue = Issue.find(1)
  7320. assert_nil issue.assigned_to_id
  7321. @request.session[:user_id] = 1
  7322. with_settings :gravatar_enabled => '1' do
  7323. get :show, :params => {:id => issue.id}
  7324. assert_select 'div.gravatar-with-child' do
  7325. assert_select 'img.gravatar', 1
  7326. end
  7327. end
  7328. end
  7329. def test_show_should_display_author_and_assignee_gravatars_when_assigned
  7330. issue = Issue.find(1)
  7331. issue.assigned_to_id = 2
  7332. issue.save!
  7333. @request.session[:user_id] = 1
  7334. with_settings :gravatar_enabled => '1' do
  7335. get :show, :params => {:id => issue.id}
  7336. assert_select 'div.gravatar-with-child' do
  7337. assert_select 'img.gravatar', 2
  7338. assert_select 'img.gravatar-child', 1
  7339. end
  7340. end
  7341. end
  7342. end