您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

issues_controller_test.rb 210KB

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