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

issues_controller_test.rb 209KB

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