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

issues_controller_test.rb 148 kB

​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
​
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898
  1. # Redmine - project management software
  2. # Copyright (C) 2006-2013 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 < ActionController::TestCase
  19. fixtures :projects,
  20. :users,
  21. :roles,
  22. :members,
  23. :member_roles,
  24. :issues,
  25. :issue_statuses,
  26. :versions,
  27. :trackers,
  28. :projects_trackers,
  29. :issue_categories,
  30. :enabled_modules,
  31. :enumerations,
  32. :attachments,
  33. :workflows,
  34. :custom_fields,
  35. :custom_values,
  36. :custom_fields_projects,
  37. :custom_fields_trackers,
  38. :time_entries,
  39. :journals,
  40. :journal_details,
  41. :queries,
  42. :repositories,
  43. :changesets
  44. include Redmine::I18n
  45. def setup
  46. User.current = nil
  47. end
  48. def test_index
  49. with_settings :default_language => "en" do
  50. get :index
  51. assert_response :success
  52. assert_template 'index'
  53. assert_not_nil assigns(:issues)
  54. assert_nil assigns(:project)
  55. # links to visible issues
  56. assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
  57. assert_select 'a[href=/issues/5]', :text => /Subproject issue/
  58. # private projects hidden
  59. assert_select 'a[href=/issues/6]', 0
  60. assert_select 'a[href=/issues/4]', 0
  61. # project column
  62. assert_select 'th', :text => /Project/
  63. end
  64. end
  65. def test_index_should_not_list_issues_when_module_disabled
  66. EnabledModule.delete_all("name = 'issue_tracking' AND project_id = 1")
  67. get :index
  68. assert_response :success
  69. assert_template 'index'
  70. assert_not_nil assigns(:issues)
  71. assert_nil assigns(:project)
  72. assert_select 'a[href=/issues/1]', 0
  73. assert_select 'a[href=/issues/5]', :text => /Subproject issue/
  74. end
  75. def test_index_should_list_visible_issues_only
  76. get :index, :per_page => 100
  77. assert_response :success
  78. assert_not_nil assigns(:issues)
  79. assert_nil assigns(:issues).detect {|issue| !issue.visible?}
  80. end
  81. def test_index_with_project
  82. Setting.display_subprojects_issues = 0
  83. get :index, :project_id => 1
  84. assert_response :success
  85. assert_template 'index'
  86. assert_not_nil assigns(:issues)
  87. assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
  88. assert_select 'a[href=/issues/5]', 0
  89. end
  90. def test_index_with_project_and_subprojects
  91. Setting.display_subprojects_issues = 1
  92. get :index, :project_id => 1
  93. assert_response :success
  94. assert_template 'index'
  95. assert_not_nil assigns(:issues)
  96. assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
  97. assert_select 'a[href=/issues/5]', :text => /Subproject issue/
  98. assert_select 'a[href=/issues/6]', 0
  99. end
  100. def test_index_with_project_and_subprojects_should_show_private_subprojects_with_permission
  101. @request.session[:user_id] = 2
  102. Setting.display_subprojects_issues = 1
  103. get :index, :project_id => 1
  104. assert_response :success
  105. assert_template 'index'
  106. assert_not_nil assigns(:issues)
  107. assert_select 'a[href=/issues/1]', :text => /Can&#x27;t print recipes/
  108. assert_select 'a[href=/issues/5]', :text => /Subproject issue/
  109. assert_select 'a[href=/issues/6]', :text => /Issue of a private subproject/
  110. end
  111. def test_index_with_project_and_default_filter
  112. get :index, :project_id => 1, :set_filter => 1
  113. assert_response :success
  114. assert_template 'index'
  115. assert_not_nil assigns(:issues)
  116. query = assigns(:query)
  117. assert_not_nil query
  118. # default filter
  119. assert_equal({'status_id' => {:operator => 'o', :values => ['']}}, query.filters)
  120. end
  121. def test_index_with_project_and_filter
  122. get :index, :project_id => 1, :set_filter => 1,
  123. :f => ['tracker_id'],
  124. :op => {'tracker_id' => '='},
  125. :v => {'tracker_id' => ['1']}
  126. assert_response :success
  127. assert_template 'index'
  128. assert_not_nil assigns(:issues)
  129. query = assigns(:query)
  130. assert_not_nil query
  131. assert_equal({'tracker_id' => {:operator => '=', :values => ['1']}}, query.filters)
  132. end
  133. def test_index_with_short_filters
  134. to_test = {
  135. 'status_id' => {
  136. 'o' => { :op => 'o', :values => [''] },
  137. 'c' => { :op => 'c', :values => [''] },
  138. '7' => { :op => '=', :values => ['7'] },
  139. '7|3|4' => { :op => '=', :values => ['7', '3', '4'] },
  140. '=7' => { :op => '=', :values => ['7'] },
  141. '!3' => { :op => '!', :values => ['3'] },
  142. '!7|3|4' => { :op => '!', :values => ['7', '3', '4'] }},
  143. 'subject' => {
  144. 'This is a subject' => { :op => '=', :values => ['This is a subject'] },
  145. 'o' => { :op => '=', :values => ['o'] },
  146. '~This is part of a subject' => { :op => '~', :values => ['This is part of a subject'] },
  147. '!~This is part of a subject' => { :op => '!~', :values => ['This is part of a subject'] }},
  148. 'tracker_id' => {
  149. '3' => { :op => '=', :values => ['3'] },
  150. '=3' => { :op => '=', :values => ['3'] }},
  151. 'start_date' => {
  152. '2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
  153. '=2011-10-12' => { :op => '=', :values => ['2011-10-12'] },
  154. '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
  155. '<=2011-10-12' => { :op => '<=', :values => ['2011-10-12'] },
  156. '><2011-10-01|2011-10-30' => { :op => '><', :values => ['2011-10-01', '2011-10-30'] },
  157. '<t+2' => { :op => '<t+', :values => ['2'] },
  158. '>t+2' => { :op => '>t+', :values => ['2'] },
  159. 't+2' => { :op => 't+', :values => ['2'] },
  160. 't' => { :op => 't', :values => [''] },
  161. 'w' => { :op => 'w', :values => [''] },
  162. '>t-2' => { :op => '>t-', :values => ['2'] },
  163. '<t-2' => { :op => '<t-', :values => ['2'] },
  164. 't-2' => { :op => 't-', :values => ['2'] }},
  165. 'created_on' => {
  166. '>=2011-10-12' => { :op => '>=', :values => ['2011-10-12'] },
  167. '<t-2' => { :op => '<t-', :values => ['2'] },
  168. '>t-2' => { :op => '>t-', :values => ['2'] },
  169. 't-2' => { :op => 't-', :values => ['2'] }},
  170. 'cf_1' => {
  171. 'c' => { :op => '=', :values => ['c'] },
  172. '!c' => { :op => '!', :values => ['c'] },
  173. '!*' => { :op => '!*', :values => [''] },
  174. '*' => { :op => '*', :values => [''] }},
  175. 'estimated_hours' => {
  176. '=13.4' => { :op => '=', :values => ['13.4'] },
  177. '>=45' => { :op => '>=', :values => ['45'] },
  178. '<=125' => { :op => '<=', :values => ['125'] },
  179. '><10.5|20.5' => { :op => '><', :values => ['10.5', '20.5'] },
  180. '!*' => { :op => '!*', :values => [''] },
  181. '*' => { :op => '*', :values => [''] }}
  182. }
  183. default_filter = { 'status_id' => {:operator => 'o', :values => [''] }}
  184. to_test.each do |field, expression_and_expected|
  185. expression_and_expected.each do |filter_expression, expected|
  186. get :index, :set_filter => 1, field => filter_expression
  187. assert_response :success
  188. assert_template 'index'
  189. assert_not_nil assigns(:issues)
  190. query = assigns(:query)
  191. assert_not_nil query
  192. assert query.has_filter?(field)
  193. assert_equal(default_filter.merge({field => {:operator => expected[:op], :values => expected[:values]}}), query.filters)
  194. end
  195. end
  196. end
  197. def test_index_with_project_and_empty_filters
  198. get :index, :project_id => 1, :set_filter => 1, :fields => ['']
  199. assert_response :success
  200. assert_template 'index'
  201. assert_not_nil assigns(:issues)
  202. query = assigns(:query)
  203. assert_not_nil query
  204. # no filter
  205. assert_equal({}, query.filters)
  206. end
  207. def test_index_with_project_custom_field_filter
  208. field = ProjectCustomField.create!(:name => 'Client', :is_filter => true, :field_format => 'string')
  209. CustomValue.create!(:custom_field => field, :customized => Project.find(3), :value => 'Foo')
  210. CustomValue.create!(:custom_field => field, :customized => Project.find(5), :value => 'Foo')
  211. filter_name = "project.cf_#{field.id}"
  212. @request.session[:user_id] = 1
  213. get :index, :set_filter => 1,
  214. :f => [filter_name],
  215. :op => {filter_name => '='},
  216. :v => {filter_name => ['Foo']}
  217. assert_response :success
  218. assert_template 'index'
  219. assert_equal [3, 5], assigns(:issues).map(&:project_id).uniq.sort
  220. end
  221. def test_index_with_query
  222. get :index, :project_id => 1, :query_id => 5
  223. assert_response :success
  224. assert_template 'index'
  225. assert_not_nil assigns(:issues)
  226. assert_nil assigns(:issue_count_by_group)
  227. end
  228. def test_index_with_query_grouped_by_tracker
  229. get :index, :project_id => 1, :query_id => 6
  230. assert_response :success
  231. assert_template 'index'
  232. assert_not_nil assigns(:issues)
  233. assert_not_nil assigns(:issue_count_by_group)
  234. end
  235. def test_index_with_query_grouped_by_list_custom_field
  236. get :index, :project_id => 1, :query_id => 9
  237. assert_response :success
  238. assert_template 'index'
  239. assert_not_nil assigns(:issues)
  240. assert_not_nil assigns(:issue_count_by_group)
  241. end
  242. def test_index_with_query_grouped_by_user_custom_field
  243. cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
  244. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  245. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  246. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  247. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  248. get :index, :project_id => 1, :set_filter => 1, :group_by => "cf_#{cf.id}"
  249. assert_response :success
  250. assert_select 'tr.group', 3
  251. assert_select 'tr.group' do
  252. assert_select 'a', :text => 'John Smith'
  253. assert_select 'span.count', :text => '1'
  254. end
  255. assert_select 'tr.group' do
  256. assert_select 'a', :text => 'Dave Lopper'
  257. assert_select 'span.count', :text => '2'
  258. end
  259. end
  260. def test_index_with_query_grouped_by_tracker
  261. 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
  262. get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc'
  263. assert_response :success
  264. trackers = assigns(:issues).map(&:tracker).uniq
  265. assert_equal [1, 2, 3], trackers.map(&:id)
  266. end
  267. def test_index_with_query_grouped_by_tracker_in_reverse_order
  268. 3.times {|i| Issue.generate!(:tracker_id => (i + 1))}
  269. get :index, :set_filter => 1, :group_by => 'tracker', :sort => 'id:desc,tracker:desc'
  270. assert_response :success
  271. trackers = assigns(:issues).map(&:tracker).uniq
  272. assert_equal [3, 2, 1], trackers.map(&:id)
  273. end
  274. def test_index_with_query_id_and_project_id_should_set_session_query
  275. get :index, :project_id => 1, :query_id => 4
  276. assert_response :success
  277. assert_kind_of Hash, session[:query]
  278. assert_equal 4, session[:query][:id]
  279. assert_equal 1, session[:query][:project_id]
  280. end
  281. def test_index_with_invalid_query_id_should_respond_404
  282. get :index, :project_id => 1, :query_id => 999
  283. assert_response 404
  284. end
  285. def test_index_with_cross_project_query_in_session_should_show_project_issues
  286. q = IssueQuery.create!(:name => "test", :user_id => 2, :is_public => false, :project => nil)
  287. @request.session[:query] = {:id => q.id, :project_id => 1}
  288. with_settings :display_subprojects_issues => '0' do
  289. get :index, :project_id => 1
  290. end
  291. assert_response :success
  292. assert_not_nil assigns(:query)
  293. assert_equal q.id, assigns(:query).id
  294. assert_equal 1, assigns(:query).project_id
  295. assert_equal [1], assigns(:issues).map(&:project_id).uniq
  296. end
  297. def test_private_query_should_not_be_available_to_other_users
  298. q = IssueQuery.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil)
  299. @request.session[:user_id] = 3
  300. get :index, :query_id => q.id
  301. assert_response 403
  302. end
  303. def test_private_query_should_be_available_to_its_user
  304. q = IssueQuery.create!(:name => "private", :user => User.find(2), :is_public => false, :project => nil)
  305. @request.session[:user_id] = 2
  306. get :index, :query_id => q.id
  307. assert_response :success
  308. end
  309. def test_public_query_should_be_available_to_other_users
  310. q = IssueQuery.create!(:name => "private", :user => User.find(2), :is_public => true, :project => nil)
  311. @request.session[:user_id] = 3
  312. get :index, :query_id => q.id
  313. assert_response :success
  314. end
  315. def test_index_should_omit_page_param_in_export_links
  316. get :index, :page => 2
  317. assert_response :success
  318. assert_select 'a.atom[href=/issues.atom]'
  319. assert_select 'a.csv[href=/issues.csv]'
  320. assert_select 'a.pdf[href=/issues.pdf]'
  321. assert_select 'form#csv-export-form[action=/issues.csv]'
  322. end
  323. def test_index_csv
  324. get :index, :format => 'csv'
  325. assert_response :success
  326. assert_not_nil assigns(:issues)
  327. assert_equal 'text/csv; header=present', @response.content_type
  328. assert @response.body.starts_with?("#,")
  329. lines = @response.body.chomp.split("\n")
  330. assert_equal assigns(:query).columns.size, lines[0].split(',').size
  331. end
  332. def test_index_csv_with_project
  333. get :index, :project_id => 1, :format => 'csv'
  334. assert_response :success
  335. assert_not_nil assigns(:issues)
  336. assert_equal 'text/csv; header=present', @response.content_type
  337. end
  338. def test_index_csv_with_description
  339. Issue.generate!(:description => 'test_index_csv_with_description')
  340. with_settings :default_language => 'en' do
  341. get :index, :format => 'csv', :description => '1'
  342. assert_response :success
  343. assert_not_nil assigns(:issues)
  344. end
  345. assert_equal 'text/csv; header=present', response.content_type
  346. headers = response.body.chomp.split("\n").first.split(',')
  347. assert_include 'Description', headers
  348. assert_include 'test_index_csv_with_description', response.body
  349. end
  350. def test_index_csv_with_spent_time_column
  351. issue = Issue.create!(:project_id => 1, :tracker_id => 1, :subject => 'test_index_csv_with_spent_time_column', :author_id => 2)
  352. TimeEntry.create!(:project => issue.project, :issue => issue, :hours => 7.33, :user => User.find(2), :spent_on => Date.today)
  353. get :index, :format => 'csv', :set_filter => '1', :c => %w(subject spent_hours)
  354. assert_response :success
  355. assert_equal 'text/csv; header=present', @response.content_type
  356. lines = @response.body.chomp.split("\n")
  357. assert_include "#{issue.id},#{issue.subject},7.33", lines
  358. end
  359. def test_index_csv_with_all_columns
  360. get :index, :format => 'csv', :columns => 'all'
  361. assert_response :success
  362. assert_not_nil assigns(:issues)
  363. assert_equal 'text/csv; header=present', @response.content_type
  364. assert_match /\A#,/, response.body
  365. lines = response.body.chomp.split("\n")
  366. assert_equal assigns(:query).available_inline_columns.size, lines[0].split(',').size
  367. end
  368. def test_index_csv_with_multi_column_field
  369. CustomField.find(1).update_attribute :multiple, true
  370. issue = Issue.find(1)
  371. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  372. issue.save!
  373. get :index, :format => 'csv', :columns => 'all'
  374. assert_response :success
  375. lines = @response.body.chomp.split("\n")
  376. assert lines.detect {|line| line.include?('"MySQL, Oracle"')}
  377. end
  378. def test_index_csv_should_format_float_custom_fields_with_csv_decimal_separator
  379. field = IssueCustomField.create!(:name => 'Float', :is_for_all => true, :tracker_ids => [1], :field_format => 'float')
  380. issue = Issue.generate!(:project_id => 1, :tracker_id => 1, :custom_field_values => {field.id => '185.6'})
  381. with_settings :default_language => 'fr' do
  382. get :index, :format => 'csv', :columns => 'all'
  383. assert_response :success
  384. issue_line = response.body.chomp.split("\n").map {|line| line.split(';')}.detect {|line| line[0]==issue.id.to_s}
  385. assert_include '185,60', issue_line
  386. end
  387. with_settings :default_language => 'en' do
  388. get :index, :format => 'csv', :columns => 'all'
  389. assert_response :success
  390. issue_line = response.body.chomp.split("\n").map {|line| line.split(',')}.detect {|line| line[0]==issue.id.to_s}
  391. assert_include '185.60', issue_line
  392. end
  393. end
  394. def test_index_csv_big_5
  395. with_settings :default_language => "zh-TW" do
  396. str_utf8 = "\xe4\xb8\x80\xe6\x9c\x88"
  397. str_big5 = "\xa4@\xa4\xeb"
  398. if str_utf8.respond_to?(:force_encoding)
  399. str_utf8.force_encoding('UTF-8')
  400. str_big5.force_encoding('Big5')
  401. end
  402. issue = Issue.generate!(:subject => str_utf8)
  403. get :index, :project_id => 1,
  404. :f => ['subject'],
  405. :op => '=', :values => [str_utf8],
  406. :format => 'csv'
  407. assert_equal 'text/csv; header=present', @response.content_type
  408. lines = @response.body.chomp.split("\n")
  409. s1 = "\xaa\xac\xbaA"
  410. if str_utf8.respond_to?(:force_encoding)
  411. s1.force_encoding('Big5')
  412. end
  413. assert_include s1, lines[0]
  414. assert_include str_big5, lines[1]
  415. end
  416. end
  417. def test_index_csv_cannot_convert_should_be_replaced_big_5
  418. with_settings :default_language => "zh-TW" do
  419. str_utf8 = "\xe4\xbb\xa5\xe5\x86\x85"
  420. if str_utf8.respond_to?(:force_encoding)
  421. str_utf8.force_encoding('UTF-8')
  422. end
  423. issue = Issue.generate!(:subject => str_utf8)
  424. get :index, :project_id => 1,
  425. :f => ['subject'],
  426. :op => '=', :values => [str_utf8],
  427. :c => ['status', 'subject'],
  428. :format => 'csv',
  429. :set_filter => 1
  430. assert_equal 'text/csv; header=present', @response.content_type
  431. lines = @response.body.chomp.split("\n")
  432. s1 = "\xaa\xac\xbaA" # status
  433. if str_utf8.respond_to?(:force_encoding)
  434. s1.force_encoding('Big5')
  435. end
  436. assert lines[0].include?(s1)
  437. s2 = lines[1].split(",")[2]
  438. if s1.respond_to?(:force_encoding)
  439. s3 = "\xa5H?" # subject
  440. s3.force_encoding('Big5')
  441. assert_equal s3, s2
  442. elsif RUBY_PLATFORM == 'java'
  443. assert_equal "??", s2
  444. else
  445. assert_equal "\xa5H???", s2
  446. end
  447. end
  448. end
  449. def test_index_csv_tw
  450. with_settings :default_language => "zh-TW" do
  451. str1 = "test_index_csv_tw"
  452. issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
  453. get :index, :project_id => 1,
  454. :f => ['subject'],
  455. :op => '=', :values => [str1],
  456. :c => ['estimated_hours', 'subject'],
  457. :format => 'csv',
  458. :set_filter => 1
  459. assert_equal 'text/csv; header=present', @response.content_type
  460. lines = @response.body.chomp.split("\n")
  461. assert_equal "#{issue.id},1234.50,#{str1}", lines[1]
  462. end
  463. end
  464. def test_index_csv_fr
  465. with_settings :default_language => "fr" do
  466. str1 = "test_index_csv_fr"
  467. issue = Issue.generate!(:subject => str1, :estimated_hours => '1234.5')
  468. get :index, :project_id => 1,
  469. :f => ['subject'],
  470. :op => '=', :values => [str1],
  471. :c => ['estimated_hours', 'subject'],
  472. :format => 'csv',
  473. :set_filter => 1
  474. assert_equal 'text/csv; header=present', @response.content_type
  475. lines = @response.body.chomp.split("\n")
  476. assert_equal "#{issue.id};1234,50;#{str1}", lines[1]
  477. end
  478. end
  479. def test_index_pdf
  480. ["en", "zh", "zh-TW", "ja", "ko"].each do |lang|
  481. with_settings :default_language => lang do
  482. get :index
  483. assert_response :success
  484. assert_template 'index'
  485. if lang == "ja"
  486. if RUBY_PLATFORM != 'java'
  487. assert_equal "CP932", l(:general_pdf_encoding)
  488. end
  489. if RUBY_PLATFORM == 'java' && l(:general_pdf_encoding) == "CP932"
  490. next
  491. end
  492. end
  493. get :index, :format => 'pdf'
  494. assert_response :success
  495. assert_not_nil assigns(:issues)
  496. assert_equal 'application/pdf', @response.content_type
  497. get :index, :project_id => 1, :format => 'pdf'
  498. assert_response :success
  499. assert_not_nil assigns(:issues)
  500. assert_equal 'application/pdf', @response.content_type
  501. get :index, :project_id => 1, :query_id => 6, :format => 'pdf'
  502. assert_response :success
  503. assert_not_nil assigns(:issues)
  504. assert_equal 'application/pdf', @response.content_type
  505. end
  506. end
  507. end
  508. def test_index_pdf_with_query_grouped_by_list_custom_field
  509. get :index, :project_id => 1, :query_id => 9, :format => 'pdf'
  510. assert_response :success
  511. assert_not_nil assigns(:issues)
  512. assert_not_nil assigns(:issue_count_by_group)
  513. assert_equal 'application/pdf', @response.content_type
  514. end
  515. def test_index_atom
  516. get :index, :project_id => 'ecookbook', :format => 'atom'
  517. assert_response :success
  518. assert_template 'common/feed'
  519. assert_equal 'application/atom+xml', response.content_type
  520. assert_select 'feed' do
  521. assert_select 'link[rel=self][href=?]', 'http://test.host/projects/ecookbook/issues.atom'
  522. assert_select 'link[rel=alternate][href=?]', 'http://test.host/projects/ecookbook/issues'
  523. assert_select 'entry link[href=?]', 'http://test.host/issues/1'
  524. end
  525. end
  526. def test_index_sort
  527. get :index, :sort => 'tracker,id:desc'
  528. assert_response :success
  529. sort_params = @request.session['issues_index_sort']
  530. assert sort_params.is_a?(String)
  531. assert_equal 'tracker,id:desc', sort_params
  532. issues = assigns(:issues)
  533. assert_not_nil issues
  534. assert !issues.empty?
  535. assert_equal issues.sort {|a,b| a.tracker == b.tracker ? b.id <=> a.id : a.tracker <=> b.tracker }.collect(&:id), issues.collect(&:id)
  536. end
  537. def test_index_sort_by_field_not_included_in_columns
  538. Setting.issue_list_default_columns = %w(subject author)
  539. get :index, :sort => 'tracker'
  540. end
  541. def test_index_sort_by_assigned_to
  542. get :index, :sort => 'assigned_to'
  543. assert_response :success
  544. assignees = assigns(:issues).collect(&:assigned_to).compact
  545. assert_equal assignees.sort, assignees
  546. end
  547. def test_index_sort_by_assigned_to_desc
  548. get :index, :sort => 'assigned_to:desc'
  549. assert_response :success
  550. assignees = assigns(:issues).collect(&:assigned_to).compact
  551. assert_equal assignees.sort.reverse, assignees
  552. end
  553. def test_index_group_by_assigned_to
  554. get :index, :group_by => 'assigned_to', :sort => 'priority'
  555. assert_response :success
  556. end
  557. def test_index_sort_by_author
  558. get :index, :sort => 'author'
  559. assert_response :success
  560. authors = assigns(:issues).collect(&:author)
  561. assert_equal authors.sort, authors
  562. end
  563. def test_index_sort_by_author_desc
  564. get :index, :sort => 'author:desc'
  565. assert_response :success
  566. authors = assigns(:issues).collect(&:author)
  567. assert_equal authors.sort.reverse, authors
  568. end
  569. def test_index_group_by_author
  570. get :index, :group_by => 'author', :sort => 'priority'
  571. assert_response :success
  572. end
  573. def test_index_sort_by_spent_hours
  574. get :index, :sort => 'spent_hours:desc'
  575. assert_response :success
  576. hours = assigns(:issues).collect(&:spent_hours)
  577. assert_equal hours.sort.reverse, hours
  578. end
  579. def test_index_sort_by_user_custom_field
  580. cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
  581. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  582. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  583. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  584. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  585. get :index, :project_id => 1, :set_filter => 1, :sort => "cf_#{cf.id},id"
  586. assert_response :success
  587. assert_equal [2, 3, 1], assigns(:issues).select {|issue| issue.custom_field_value(cf).present?}.map(&:id)
  588. end
  589. def test_index_with_columns
  590. columns = ['tracker', 'subject', 'assigned_to']
  591. get :index, :set_filter => 1, :c => columns
  592. assert_response :success
  593. # query should use specified columns
  594. query = assigns(:query)
  595. assert_kind_of IssueQuery, query
  596. assert_equal columns, query.column_names.map(&:to_s)
  597. # columns should be stored in session
  598. assert_kind_of Hash, session[:query]
  599. assert_kind_of Array, session[:query][:column_names]
  600. assert_equal columns, session[:query][:column_names].map(&:to_s)
  601. # ensure only these columns are kept in the selected columns list
  602. assert_select 'select#selected_columns option' do
  603. assert_select 'option', 3
  604. assert_select 'option[value=tracker]'
  605. assert_select 'option[value=project]', 0
  606. end
  607. end
  608. def test_index_without_project_should_implicitly_add_project_column_to_default_columns
  609. Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
  610. get :index, :set_filter => 1
  611. # query should use specified columns
  612. query = assigns(:query)
  613. assert_kind_of IssueQuery, query
  614. assert_equal [:id, :project, :tracker, :subject, :assigned_to], query.columns.map(&:name)
  615. end
  616. def test_index_without_project_and_explicit_default_columns_should_not_add_project_column
  617. Setting.issue_list_default_columns = ['tracker', 'subject', 'assigned_to']
  618. columns = ['id', 'tracker', 'subject', 'assigned_to']
  619. get :index, :set_filter => 1, :c => columns
  620. # query should use specified columns
  621. query = assigns(:query)
  622. assert_kind_of IssueQuery, query
  623. assert_equal columns.map(&:to_sym), query.columns.map(&:name)
  624. end
  625. def test_index_with_custom_field_column
  626. columns = %w(tracker subject cf_2)
  627. get :index, :set_filter => 1, :c => columns
  628. assert_response :success
  629. # query should use specified columns
  630. query = assigns(:query)
  631. assert_kind_of IssueQuery, query
  632. assert_equal columns, query.column_names.map(&:to_s)
  633. assert_select 'table.issues td.cf_2.string'
  634. end
  635. def test_index_with_multi_custom_field_column
  636. field = CustomField.find(1)
  637. field.update_attribute :multiple, true
  638. issue = Issue.find(1)
  639. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  640. issue.save!
  641. get :index, :set_filter => 1, :c => %w(tracker subject cf_1)
  642. assert_response :success
  643. assert_select 'table.issues td.cf_1', :text => 'MySQL, Oracle'
  644. end
  645. def test_index_with_multi_user_custom_field_column
  646. field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
  647. :tracker_ids => [1], :is_for_all => true)
  648. issue = Issue.find(1)
  649. issue.custom_field_values = {field.id => ['2', '3']}
  650. issue.save!
  651. get :index, :set_filter => 1, :c => ['tracker', 'subject', "cf_#{field.id}"]
  652. assert_response :success
  653. assert_select "table.issues td.cf_#{field.id}" do
  654. assert_select 'a', 2
  655. assert_select 'a[href=?]', '/users/2', :text => 'John Smith'
  656. assert_select 'a[href=?]', '/users/3', :text => 'Dave Lopper'
  657. end
  658. end
  659. def test_index_with_date_column
  660. with_settings :date_format => '%d/%m/%Y' do
  661. Issue.find(1).update_attribute :start_date, '1987-08-24'
  662. get :index, :set_filter => 1, :c => %w(start_date)
  663. assert_select "table.issues td.start_date", :text => '24/08/1987'
  664. end
  665. end
  666. def test_index_with_done_ratio_column
  667. Issue.find(1).update_attribute :done_ratio, 40
  668. get :index, :set_filter => 1, :c => %w(done_ratio)
  669. assert_select 'table.issues td.done_ratio' do
  670. assert_select 'table.progress' do
  671. assert_select 'td.closed[style=?]', 'width: 40%;'
  672. end
  673. end
  674. end
  675. def test_index_with_spent_hours_column
  676. get :index, :set_filter => 1, :c => %w(subject spent_hours)
  677. assert_select 'table.issues tr#issue-3 td.spent_hours', :text => '1.00'
  678. end
  679. def test_index_should_not_show_spent_hours_column_without_permission
  680. Role.anonymous.remove_permission! :view_time_entries
  681. get :index, :set_filter => 1, :c => %w(subject spent_hours)
  682. assert_select 'td.spent_hours', 0
  683. end
  684. def test_index_with_fixed_version_column
  685. get :index, :set_filter => 1, :c => %w(fixed_version)
  686. assert_select 'table.issues td.fixed_version' do
  687. assert_select 'a[href=?]', '/versions/2', :text => '1.0'
  688. end
  689. end
  690. def test_index_with_relations_column
  691. IssueRelation.delete_all
  692. IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(1), :issue_to => Issue.find(7))
  693. IssueRelation.create!(:relation_type => "relates", :issue_from => Issue.find(8), :issue_to => Issue.find(1))
  694. IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(1), :issue_to => Issue.find(11))
  695. IssueRelation.create!(:relation_type => "blocks", :issue_from => Issue.find(12), :issue_to => Issue.find(2))
  696. get :index, :set_filter => 1, :c => %w(subject relations)
  697. assert_response :success
  698. assert_select "tr#issue-1 td.relations" do
  699. assert_select "span", 3
  700. assert_select "span", :text => "Related to #7"
  701. assert_select "span", :text => "Related to #8"
  702. assert_select "span", :text => "Blocks #11"
  703. end
  704. assert_select "tr#issue-2 td.relations" do
  705. assert_select "span", 1
  706. assert_select "span", :text => "Blocked by #12"
  707. end
  708. assert_select "tr#issue-3 td.relations" do
  709. assert_select "span", 0
  710. end
  711. get :index, :set_filter => 1, :c => %w(relations), :format => 'csv'
  712. assert_response :success
  713. assert_equal 'text/csv; header=present', response.content_type
  714. lines = response.body.chomp.split("\n")
  715. assert_include '1,"Related to #7, Related to #8, Blocks #11"', lines
  716. assert_include '2,Blocked by #12', lines
  717. assert_include '3,""', lines
  718. get :index, :set_filter => 1, :c => %w(subject relations), :format => 'pdf'
  719. assert_response :success
  720. assert_equal 'application/pdf', response.content_type
  721. end
  722. def test_index_with_description_column
  723. get :index, :set_filter => 1, :c => %w(subject description)
  724. assert_select 'table.issues thead th', 3 # columns: chekbox + id + subject
  725. assert_select 'td.description[colspan=3]', :text => 'Unable to print recipes'
  726. get :index, :set_filter => 1, :c => %w(subject description), :format => 'pdf'
  727. assert_response :success
  728. assert_equal 'application/pdf', response.content_type
  729. end
  730. def test_index_send_html_if_query_is_invalid
  731. get :index, :f => ['start_date'], :op => {:start_date => '='}
  732. assert_equal 'text/html', @response.content_type
  733. assert_template 'index'
  734. end
  735. def test_index_send_nothing_if_query_is_invalid
  736. get :index, :f => ['start_date'], :op => {:start_date => '='}, :format => 'csv'
  737. assert_equal 'text/csv', @response.content_type
  738. assert @response.body.blank?
  739. end
  740. def test_show_by_anonymous
  741. get :show, :id => 1
  742. assert_response :success
  743. assert_template 'show'
  744. assert_equal Issue.find(1), assigns(:issue)
  745. assert_select 'div.issue div.description', :text => /Unable to print recipes/
  746. # anonymous role is allowed to add a note
  747. assert_select 'form#issue-form' do
  748. assert_select 'fieldset' do
  749. assert_select 'legend', :text => 'Notes'
  750. assert_select 'textarea[name=?]', 'issue[notes]'
  751. end
  752. end
  753. assert_select 'title', :text => "Bug #1: Can&#x27;t print recipes - eCookbook - Redmine"
  754. end
  755. def test_show_by_manager
  756. @request.session[:user_id] = 2
  757. get :show, :id => 1
  758. assert_response :success
  759. assert_select 'a', :text => /Quote/
  760. assert_select 'form#issue-form' do
  761. assert_select 'fieldset' do
  762. assert_select 'legend', :text => 'Change properties'
  763. assert_select 'input[name=?]', 'issue[subject]'
  764. end
  765. assert_select 'fieldset' do
  766. assert_select 'legend', :text => 'Log time'
  767. assert_select 'input[name=?]', 'time_entry[hours]'
  768. end
  769. assert_select 'fieldset' do
  770. assert_select 'legend', :text => 'Notes'
  771. assert_select 'textarea[name=?]', 'issue[notes]'
  772. end
  773. end
  774. end
  775. def test_show_should_display_update_form
  776. @request.session[:user_id] = 2
  777. get :show, :id => 1
  778. assert_response :success
  779. assert_select 'form#issue-form' do
  780. assert_select 'input[name=?]', 'issue[is_private]'
  781. assert_select 'select[name=?]', 'issue[project_id]'
  782. assert_select 'select[name=?]', 'issue[tracker_id]'
  783. assert_select 'input[name=?]', 'issue[subject]'
  784. assert_select 'textarea[name=?]', 'issue[description]'
  785. assert_select 'select[name=?]', 'issue[status_id]'
  786. assert_select 'select[name=?]', 'issue[priority_id]'
  787. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  788. assert_select 'select[name=?]', 'issue[category_id]'
  789. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  790. assert_select 'input[name=?]', 'issue[parent_issue_id]'
  791. assert_select 'input[name=?]', 'issue[start_date]'
  792. assert_select 'input[name=?]', 'issue[due_date]'
  793. assert_select 'select[name=?]', 'issue[done_ratio]'
  794. assert_select 'input[name=?]', 'issue[custom_field_values][2]'
  795. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  796. assert_select 'textarea[name=?]', 'issue[notes]'
  797. end
  798. end
  799. def test_show_should_display_update_form_with_minimal_permissions
  800. Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
  801. WorkflowTransition.delete_all :role_id => 1
  802. @request.session[:user_id] = 2
  803. get :show, :id => 1
  804. assert_response :success
  805. assert_select 'form#issue-form' do
  806. assert_select 'input[name=?]', 'issue[is_private]', 0
  807. assert_select 'select[name=?]', 'issue[project_id]', 0
  808. assert_select 'select[name=?]', 'issue[tracker_id]', 0
  809. assert_select 'input[name=?]', 'issue[subject]', 0
  810. assert_select 'textarea[name=?]', 'issue[description]', 0
  811. assert_select 'select[name=?]', 'issue[status_id]', 0
  812. assert_select 'select[name=?]', 'issue[priority_id]', 0
  813. assert_select 'select[name=?]', 'issue[assigned_to_id]', 0
  814. assert_select 'select[name=?]', 'issue[category_id]', 0
  815. assert_select 'select[name=?]', 'issue[fixed_version_id]', 0
  816. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  817. assert_select 'input[name=?]', 'issue[start_date]', 0
  818. assert_select 'input[name=?]', 'issue[due_date]', 0
  819. assert_select 'select[name=?]', 'issue[done_ratio]', 0
  820. assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
  821. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  822. assert_select 'textarea[name=?]', 'issue[notes]'
  823. end
  824. end
  825. def test_show_should_display_update_form_with_workflow_permissions
  826. Role.find(1).update_attribute :permissions, [:view_issues, :add_issue_notes]
  827. @request.session[:user_id] = 2
  828. get :show, :id => 1
  829. assert_response :success
  830. assert_select 'form#issue-form' do
  831. assert_select 'input[name=?]', 'issue[is_private]', 0
  832. assert_select 'select[name=?]', 'issue[project_id]', 0
  833. assert_select 'select[name=?]', 'issue[tracker_id]', 0
  834. assert_select 'input[name=?]', 'issue[subject]', 0
  835. assert_select 'textarea[name=?]', 'issue[description]', 0
  836. assert_select 'select[name=?]', 'issue[status_id]'
  837. assert_select 'select[name=?]', 'issue[priority_id]', 0
  838. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  839. assert_select 'select[name=?]', 'issue[category_id]', 0
  840. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  841. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  842. assert_select 'input[name=?]', 'issue[start_date]', 0
  843. assert_select 'input[name=?]', 'issue[due_date]', 0
  844. assert_select 'select[name=?]', 'issue[done_ratio]'
  845. assert_select 'input[name=?]', 'issue[custom_field_values][2]', 0
  846. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  847. assert_select 'textarea[name=?]', 'issue[notes]'
  848. end
  849. end
  850. def test_show_should_not_display_update_form_without_permissions
  851. Role.find(1).update_attribute :permissions, [:view_issues]
  852. @request.session[:user_id] = 2
  853. get :show, :id => 1
  854. assert_response :success
  855. assert_select 'form#issue-form', 0
  856. end
  857. def test_update_form_should_not_display_inactive_enumerations
  858. assert !IssuePriority.find(15).active?
  859. @request.session[:user_id] = 2
  860. get :show, :id => 1
  861. assert_response :success
  862. assert_select 'form#issue-form' do
  863. assert_select 'select[name=?]', 'issue[priority_id]' do
  864. assert_select 'option[value=4]'
  865. assert_select 'option[value=15]', 0
  866. end
  867. end
  868. end
  869. def test_update_form_should_allow_attachment_upload
  870. @request.session[:user_id] = 2
  871. get :show, :id => 1
  872. assert_select 'form#issue-form[method=post][enctype=multipart/form-data]' do
  873. assert_select 'input[type=file][name=?]', 'attachments[dummy][file]'
  874. end
  875. end
  876. def test_show_should_deny_anonymous_access_without_permission
  877. Role.anonymous.remove_permission!(:view_issues)
  878. get :show, :id => 1
  879. assert_response :redirect
  880. end
  881. def test_show_should_deny_anonymous_access_to_private_issue
  882. Issue.update_all(["is_private = ?", true], "id = 1")
  883. get :show, :id => 1
  884. assert_response :redirect
  885. end
  886. def test_show_should_deny_non_member_access_without_permission
  887. Role.non_member.remove_permission!(:view_issues)
  888. @request.session[:user_id] = 9
  889. get :show, :id => 1
  890. assert_response 403
  891. end
  892. def test_show_should_deny_non_member_access_to_private_issue
  893. Issue.update_all(["is_private = ?", true], "id = 1")
  894. @request.session[:user_id] = 9
  895. get :show, :id => 1
  896. assert_response 403
  897. end
  898. def test_show_should_deny_member_access_without_permission
  899. Role.find(1).remove_permission!(:view_issues)
  900. @request.session[:user_id] = 2
  901. get :show, :id => 1
  902. assert_response 403
  903. end
  904. def test_show_should_deny_member_access_to_private_issue_without_permission
  905. Issue.update_all(["is_private = ?", true], "id = 1")
  906. @request.session[:user_id] = 3
  907. get :show, :id => 1
  908. assert_response 403
  909. end
  910. def test_show_should_allow_author_access_to_private_issue
  911. Issue.update_all(["is_private = ?, author_id = 3", true], "id = 1")
  912. @request.session[:user_id] = 3
  913. get :show, :id => 1
  914. assert_response :success
  915. end
  916. def test_show_should_allow_assignee_access_to_private_issue
  917. Issue.update_all(["is_private = ?, assigned_to_id = 3", true], "id = 1")
  918. @request.session[:user_id] = 3
  919. get :show, :id => 1
  920. assert_response :success
  921. end
  922. def test_show_should_allow_member_access_to_private_issue_with_permission
  923. Issue.update_all(["is_private = ?", true], "id = 1")
  924. User.find(3).roles_for_project(Project.find(1)).first.update_attribute :issues_visibility, 'all'
  925. @request.session[:user_id] = 3
  926. get :show, :id => 1
  927. assert_response :success
  928. end
  929. def test_show_should_not_disclose_relations_to_invisible_issues
  930. Setting.cross_project_issue_relations = '1'
  931. IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(2), :relation_type => 'relates')
  932. # Relation to a private project issue
  933. IssueRelation.create!(:issue_from => Issue.find(1), :issue_to => Issue.find(4), :relation_type => 'relates')
  934. get :show, :id => 1
  935. assert_response :success
  936. assert_select 'div#relations' do
  937. assert_select 'a', :text => /#2$/
  938. assert_select 'a', :text => /#4$/, :count => 0
  939. end
  940. end
  941. def test_show_should_list_subtasks
  942. Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
  943. get :show, :id => 1
  944. assert_response :success
  945. assert_select 'div#issue_tree' do
  946. assert_select 'td.subject', :text => /Child Issue/
  947. end
  948. end
  949. def test_show_should_list_parents
  950. issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :parent_issue_id => 1, :subject => 'Child Issue')
  951. get :show, :id => issue.id
  952. assert_response :success
  953. assert_select 'div.subject' do
  954. assert_select 'h3', 'Child Issue'
  955. assert_select 'a[href=/issues/1]'
  956. end
  957. end
  958. def test_show_should_not_display_prev_next_links_without_query_in_session
  959. get :show, :id => 1
  960. assert_response :success
  961. assert_nil assigns(:prev_issue_id)
  962. assert_nil assigns(:next_issue_id)
  963. assert_select 'div.next-prev-links', 0
  964. end
  965. def test_show_should_display_prev_next_links_with_query_in_session
  966. @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
  967. @request.session['issues_index_sort'] = 'id'
  968. with_settings :display_subprojects_issues => '0' do
  969. get :show, :id => 3
  970. end
  971. assert_response :success
  972. # Previous and next issues for all projects
  973. assert_equal 2, assigns(:prev_issue_id)
  974. assert_equal 5, assigns(:next_issue_id)
  975. count = Issue.open.visible.count
  976. assert_select 'div.next-prev-links' do
  977. assert_select 'a[href=/issues/2]', :text => /Previous/
  978. assert_select 'a[href=/issues/5]', :text => /Next/
  979. assert_select 'span.position', :text => "3 of #{count}"
  980. end
  981. end
  982. def test_show_should_display_prev_next_links_with_saved_query_in_session
  983. query = IssueQuery.create!(:name => 'test', :is_public => true, :user_id => 1,
  984. :filters => {'status_id' => {:values => ['5'], :operator => '='}},
  985. :sort_criteria => [['id', 'asc']])
  986. @request.session[:query] = {:id => query.id, :project_id => nil}
  987. get :show, :id => 11
  988. assert_response :success
  989. assert_equal query, assigns(:query)
  990. # Previous and next issues for all projects
  991. assert_equal 8, assigns(:prev_issue_id)
  992. assert_equal 12, assigns(:next_issue_id)
  993. assert_select 'div.next-prev-links' do
  994. assert_select 'a[href=/issues/8]', :text => /Previous/
  995. assert_select 'a[href=/issues/12]', :text => /Next/
  996. end
  997. end
  998. def test_show_should_display_prev_next_links_with_query_and_sort_on_association
  999. @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => nil}
  1000. %w(project tracker status priority author assigned_to category fixed_version).each do |assoc_sort|
  1001. @request.session['issues_index_sort'] = assoc_sort
  1002. get :show, :id => 3
  1003. assert_response :success, "Wrong response status for #{assoc_sort} sort"
  1004. assert_select 'div.next-prev-links' do
  1005. assert_select 'a', :text => /(Previous|Next)/
  1006. end
  1007. end
  1008. end
  1009. def test_show_should_display_prev_next_links_with_project_query_in_session
  1010. @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
  1011. @request.session['issues_index_sort'] = 'id'
  1012. with_settings :display_subprojects_issues => '0' do
  1013. get :show, :id => 3
  1014. end
  1015. assert_response :success
  1016. # Previous and next issues inside project
  1017. assert_equal 2, assigns(:prev_issue_id)
  1018. assert_equal 7, assigns(:next_issue_id)
  1019. assert_select 'div.next-prev-links' do
  1020. assert_select 'a[href=/issues/2]', :text => /Previous/
  1021. assert_select 'a[href=/issues/7]', :text => /Next/
  1022. end
  1023. end
  1024. def test_show_should_not_display_prev_link_for_first_issue
  1025. @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'o'}}, :project_id => 1}
  1026. @request.session['issues_index_sort'] = 'id'
  1027. with_settings :display_subprojects_issues => '0' do
  1028. get :show, :id => 1
  1029. end
  1030. assert_response :success
  1031. assert_nil assigns(:prev_issue_id)
  1032. assert_equal 2, assigns(:next_issue_id)
  1033. assert_select 'div.next-prev-links' do
  1034. assert_select 'a', :text => /Previous/, :count => 0
  1035. assert_select 'a[href=/issues/2]', :text => /Next/
  1036. end
  1037. end
  1038. def test_show_should_not_display_prev_next_links_for_issue_not_in_query_results
  1039. @request.session[:query] = {:filters => {'status_id' => {:values => [''], :operator => 'c'}}, :project_id => 1}
  1040. @request.session['issues_index_sort'] = 'id'
  1041. get :show, :id => 1
  1042. assert_response :success
  1043. assert_nil assigns(:prev_issue_id)
  1044. assert_nil assigns(:next_issue_id)
  1045. assert_select 'a', :text => /Previous/, :count => 0
  1046. assert_select 'a', :text => /Next/, :count => 0
  1047. end
  1048. def test_show_show_should_display_prev_next_links_with_query_sort_by_user_custom_field
  1049. cf = IssueCustomField.create!(:name => 'User', :is_for_all => true, :tracker_ids => [1,2,3], :field_format => 'user')
  1050. CustomValue.create!(:custom_field => cf, :customized => Issue.find(1), :value => '2')
  1051. CustomValue.create!(:custom_field => cf, :customized => Issue.find(2), :value => '3')
  1052. CustomValue.create!(:custom_field => cf, :customized => Issue.find(3), :value => '3')
  1053. CustomValue.create!(:custom_field => cf, :customized => Issue.find(5), :value => '')
  1054. query = IssueQuery.create!(:name => 'test', :is_public => true, :user_id => 1, :filters => {},
  1055. :sort_criteria => [["cf_#{cf.id}", 'asc'], ['id', 'asc']])
  1056. @request.session[:query] = {:id => query.id, :project_id => nil}
  1057. get :show, :id => 3
  1058. assert_response :success
  1059. assert_equal 2, assigns(:prev_issue_id)
  1060. assert_equal 1, assigns(:next_issue_id)
  1061. assert_select 'div.next-prev-links' do
  1062. assert_select 'a[href=/issues/2]', :text => /Previous/
  1063. assert_select 'a[href=/issues/1]', :text => /Next/
  1064. end
  1065. end
  1066. def test_show_should_display_link_to_the_assignee
  1067. get :show, :id => 2
  1068. assert_response :success
  1069. assert_select '.assigned-to' do
  1070. assert_select 'a[href=/users/3]'
  1071. end
  1072. end
  1073. def test_show_should_display_visible_changesets_from_other_projects
  1074. project = Project.find(2)
  1075. issue = project.issues.first
  1076. issue.changeset_ids = [102]
  1077. issue.save!
  1078. # changesets from other projects should be displayed even if repository
  1079. # is disabled on issue's project
  1080. project.disable_module! :repository
  1081. @request.session[:user_id] = 2
  1082. get :show, :id => issue.id
  1083. assert_select 'a[href=?]', '/projects/ecookbook/repository/revisions/3'
  1084. end
  1085. def test_show_should_display_watchers
  1086. @request.session[:user_id] = 2
  1087. Issue.find(1).add_watcher User.find(2)
  1088. get :show, :id => 1
  1089. assert_select 'div#watchers ul' do
  1090. assert_select 'li' do
  1091. assert_select 'a[href=/users/2]'
  1092. assert_select 'a img[alt=Delete]'
  1093. end
  1094. end
  1095. end
  1096. def test_show_should_display_watchers_with_gravatars
  1097. @request.session[:user_id] = 2
  1098. Issue.find(1).add_watcher User.find(2)
  1099. with_settings :gravatar_enabled => '1' do
  1100. get :show, :id => 1
  1101. end
  1102. assert_select 'div#watchers ul' do
  1103. assert_select 'li' do
  1104. assert_select 'img.gravatar'
  1105. assert_select 'a[href=/users/2]'
  1106. assert_select 'a img[alt=Delete]'
  1107. end
  1108. end
  1109. end
  1110. def test_show_with_thumbnails_enabled_should_display_thumbnails
  1111. @request.session[:user_id] = 2
  1112. with_settings :thumbnails_enabled => '1' do
  1113. get :show, :id => 14
  1114. assert_response :success
  1115. end
  1116. assert_select 'div.thumbnails' do
  1117. assert_select 'a[href=/attachments/16/testfile.png]' do
  1118. assert_select 'img[src=/attachments/thumbnail/16]'
  1119. end
  1120. end
  1121. end
  1122. def test_show_with_thumbnails_disabled_should_not_display_thumbnails
  1123. @request.session[:user_id] = 2
  1124. with_settings :thumbnails_enabled => '0' do
  1125. get :show, :id => 14
  1126. assert_response :success
  1127. end
  1128. assert_select 'div.thumbnails', 0
  1129. end
  1130. def test_show_with_multi_custom_field
  1131. field = CustomField.find(1)
  1132. field.update_attribute :multiple, true
  1133. issue = Issue.find(1)
  1134. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  1135. issue.save!
  1136. get :show, :id => 1
  1137. assert_response :success
  1138. assert_select 'td', :text => 'MySQL, Oracle'
  1139. end
  1140. def test_show_with_multi_user_custom_field
  1141. field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
  1142. :tracker_ids => [1], :is_for_all => true)
  1143. issue = Issue.find(1)
  1144. issue.custom_field_values = {field.id => ['2', '3']}
  1145. issue.save!
  1146. get :show, :id => 1
  1147. assert_response :success
  1148. # TODO: should display links
  1149. assert_select 'td', :text => 'Dave Lopper, John Smith'
  1150. end
  1151. def test_show_should_display_private_notes_with_permission_only
  1152. journal = Journal.create!(:journalized => Issue.find(2), :notes => 'Privates notes', :private_notes => true, :user_id => 1)
  1153. @request.session[:user_id] = 2
  1154. get :show, :id => 2
  1155. assert_response :success
  1156. assert_include journal, assigns(:journals)
  1157. Role.find(1).remove_permission! :view_private_notes
  1158. get :show, :id => 2
  1159. assert_response :success
  1160. assert_not_include journal, assigns(:journals)
  1161. end
  1162. def test_show_atom
  1163. get :show, :id => 2, :format => 'atom'
  1164. assert_response :success
  1165. assert_template 'journals/index'
  1166. # Inline image
  1167. assert_select 'content', :text => Regexp.new(Regexp.quote('http://test.host/attachments/download/10'))
  1168. end
  1169. def test_show_export_to_pdf
  1170. get :show, :id => 3, :format => 'pdf'
  1171. assert_response :success
  1172. assert_equal 'application/pdf', @response.content_type
  1173. assert @response.body.starts_with?('%PDF')
  1174. assert_not_nil assigns(:issue)
  1175. end
  1176. def test_show_export_to_pdf_with_ancestors
  1177. issue = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
  1178. get :show, :id => issue.id, :format => 'pdf'
  1179. assert_response :success
  1180. assert_equal 'application/pdf', @response.content_type
  1181. assert @response.body.starts_with?('%PDF')
  1182. end
  1183. def test_show_export_to_pdf_with_descendants
  1184. c1 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
  1185. c2 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => 1)
  1186. c3 = Issue.generate!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'child', :parent_issue_id => c1.id)
  1187. get :show, :id => 1, :format => 'pdf'
  1188. assert_response :success
  1189. assert_equal 'application/pdf', @response.content_type
  1190. assert @response.body.starts_with?('%PDF')
  1191. end
  1192. def test_show_export_to_pdf_with_journals
  1193. get :show, :id => 1, :format => 'pdf'
  1194. assert_response :success
  1195. assert_equal 'application/pdf', @response.content_type
  1196. assert @response.body.starts_with?('%PDF')
  1197. end
  1198. def test_show_export_to_pdf_with_changesets
  1199. Issue.find(3).changesets = Changeset.find_all_by_id(100, 101, 102)
  1200. get :show, :id => 3, :format => 'pdf'
  1201. assert_response :success
  1202. assert_equal 'application/pdf', @response.content_type
  1203. assert @response.body.starts_with?('%PDF')
  1204. end
  1205. def test_show_invalid_should_respond_with_404
  1206. get :show, :id => 999
  1207. assert_response 404
  1208. end
  1209. def test_get_new
  1210. @request.session[:user_id] = 2
  1211. get :new, :project_id => 1, :tracker_id => 1
  1212. assert_response :success
  1213. assert_template 'new'
  1214. assert_select 'form#issue-form' do
  1215. assert_select 'input[name=?]', 'issue[is_private]'
  1216. assert_select 'select[name=?]', 'issue[project_id]', 0
  1217. assert_select 'select[name=?]', 'issue[tracker_id]'
  1218. assert_select 'input[name=?]', 'issue[subject]'
  1219. assert_select 'textarea[name=?]', 'issue[description]'
  1220. assert_select 'select[name=?]', 'issue[status_id]'
  1221. assert_select 'select[name=?]', 'issue[priority_id]'
  1222. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  1223. assert_select 'select[name=?]', 'issue[category_id]'
  1224. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  1225. assert_select 'input[name=?]', 'issue[parent_issue_id]'
  1226. assert_select 'input[name=?]', 'issue[start_date]'
  1227. assert_select 'input[name=?]', 'issue[due_date]'
  1228. assert_select 'select[name=?]', 'issue[done_ratio]'
  1229. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
  1230. assert_select 'input[name=?]', 'issue[watcher_user_ids][]'
  1231. end
  1232. # Be sure we don't display inactive IssuePriorities
  1233. assert ! IssuePriority.find(15).active?
  1234. assert_select 'select[name=?]', 'issue[priority_id]' do
  1235. assert_select 'option[value=15]', 0
  1236. end
  1237. end
  1238. def test_get_new_with_minimal_permissions
  1239. Role.find(1).update_attribute :permissions, [:add_issues]
  1240. WorkflowTransition.delete_all :role_id => 1
  1241. @request.session[:user_id] = 2
  1242. get :new, :project_id => 1, :tracker_id => 1
  1243. assert_response :success
  1244. assert_template 'new'
  1245. assert_select 'form#issue-form' do
  1246. assert_select 'input[name=?]', 'issue[is_private]', 0
  1247. assert_select 'select[name=?]', 'issue[project_id]', 0
  1248. assert_select 'select[name=?]', 'issue[tracker_id]'
  1249. assert_select 'input[name=?]', 'issue[subject]'
  1250. assert_select 'textarea[name=?]', 'issue[description]'
  1251. assert_select 'select[name=?]', 'issue[status_id]'
  1252. assert_select 'select[name=?]', 'issue[priority_id]'
  1253. assert_select 'select[name=?]', 'issue[assigned_to_id]'
  1254. assert_select 'select[name=?]', 'issue[category_id]'
  1255. assert_select 'select[name=?]', 'issue[fixed_version_id]'
  1256. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  1257. assert_select 'input[name=?]', 'issue[start_date]'
  1258. assert_select 'input[name=?]', 'issue[due_date]'
  1259. assert_select 'select[name=?]', 'issue[done_ratio]'
  1260. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Default string'
  1261. assert_select 'input[name=?]', 'issue[watcher_user_ids][]', 0
  1262. end
  1263. end
  1264. def test_get_new_with_list_custom_field
  1265. @request.session[:user_id] = 2
  1266. get :new, :project_id => 1, :tracker_id => 1
  1267. assert_response :success
  1268. assert_template 'new'
  1269. assert_select 'select.list_cf[name=?]', 'issue[custom_field_values][1]' do
  1270. assert_select 'option', 4
  1271. assert_select 'option[value=MySQL]', :text => 'MySQL'
  1272. end
  1273. end
  1274. def test_get_new_with_multi_custom_field
  1275. field = IssueCustomField.find(1)
  1276. field.update_attribute :multiple, true
  1277. @request.session[:user_id] = 2
  1278. get :new, :project_id => 1, :tracker_id => 1
  1279. assert_response :success
  1280. assert_template 'new'
  1281. assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
  1282. assert_select 'option', 3
  1283. assert_select 'option[value=MySQL]', :text => 'MySQL'
  1284. end
  1285. assert_select 'input[name=?][type=hidden][value=?]', 'issue[custom_field_values][1][]', ''
  1286. end
  1287. def test_get_new_with_multi_user_custom_field
  1288. field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
  1289. :tracker_ids => [1], :is_for_all => true)
  1290. @request.session[:user_id] = 2
  1291. get :new, :project_id => 1, :tracker_id => 1
  1292. assert_response :success
  1293. assert_template 'new'
  1294. assert_select 'select[name=?][multiple=multiple]', "issue[custom_field_values][#{field.id}][]" do
  1295. assert_select 'option', Project.find(1).users.count
  1296. assert_select 'option[value=2]', :text => 'John Smith'
  1297. end
  1298. assert_select 'input[name=?][type=hidden][value=?]', "issue[custom_field_values][#{field.id}][]", ''
  1299. end
  1300. def test_get_new_with_date_custom_field
  1301. field = IssueCustomField.create!(:name => 'Date', :field_format => 'date', :tracker_ids => [1], :is_for_all => true)
  1302. @request.session[:user_id] = 2
  1303. get :new, :project_id => 1, :tracker_id => 1
  1304. assert_response :success
  1305. assert_select 'input[name=?]', "issue[custom_field_values][#{field.id}]"
  1306. end
  1307. def test_get_new_with_text_custom_field
  1308. field = IssueCustomField.create!(:name => 'Text', :field_format => 'text', :tracker_ids => [1], :is_for_all => true)
  1309. @request.session[:user_id] = 2
  1310. get :new, :project_id => 1, :tracker_id => 1
  1311. assert_response :success
  1312. assert_select 'textarea[name=?]', "issue[custom_field_values][#{field.id}]"
  1313. end
  1314. def test_get_new_without_default_start_date_is_creation_date
  1315. Setting.default_issue_start_date_to_creation_date = 0
  1316. @request.session[:user_id] = 2
  1317. get :new, :project_id => 1, :tracker_id => 1
  1318. assert_response :success
  1319. assert_template 'new'
  1320. assert_select 'input[name=?]', 'issue[start_date]'
  1321. assert_select 'input[name=?][value]', 'issue[start_date]', 0
  1322. end
  1323. def test_get_new_with_default_start_date_is_creation_date
  1324. Setting.default_issue_start_date_to_creation_date = 1
  1325. @request.session[:user_id] = 2
  1326. get :new, :project_id => 1, :tracker_id => 1
  1327. assert_response :success
  1328. assert_template 'new'
  1329. assert_select 'input[name=?][value=?]', 'issue[start_date]', Date.today.to_s
  1330. end
  1331. def test_get_new_form_should_allow_attachment_upload
  1332. @request.session[:user_id] = 2
  1333. get :new, :project_id => 1, :tracker_id => 1
  1334. assert_select 'form[id=issue-form][method=post][enctype=multipart/form-data]' do
  1335. assert_select 'input[name=?][type=file]', 'attachments[dummy][file]'
  1336. end
  1337. end
  1338. def test_get_new_should_prefill_the_form_from_params
  1339. @request.session[:user_id] = 2
  1340. get :new, :project_id => 1,
  1341. :issue => {:tracker_id => 3, :description => 'Prefilled', :custom_field_values => {'2' => 'Custom field value'}}
  1342. issue = assigns(:issue)
  1343. assert_equal 3, issue.tracker_id
  1344. assert_equal 'Prefilled', issue.description
  1345. assert_equal 'Custom field value', issue.custom_field_value(2)
  1346. assert_select 'select[name=?]', 'issue[tracker_id]' do
  1347. assert_select 'option[value=3][selected=selected]'
  1348. end
  1349. assert_select 'textarea[name=?]', 'issue[description]', :text => /Prefilled/
  1350. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Custom field value'
  1351. end
  1352. def test_get_new_should_mark_required_fields
  1353. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1354. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1355. WorkflowPermission.delete_all
  1356. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'required')
  1357. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
  1358. @request.session[:user_id] = 2
  1359. get :new, :project_id => 1
  1360. assert_response :success
  1361. assert_template 'new'
  1362. assert_select 'label[for=issue_start_date]' do
  1363. assert_select 'span[class=required]', 0
  1364. end
  1365. assert_select 'label[for=issue_due_date]' do
  1366. assert_select 'span[class=required]'
  1367. end
  1368. assert_select 'label[for=?]', "issue_custom_field_values_#{cf1.id}" do
  1369. assert_select 'span[class=required]', 0
  1370. end
  1371. assert_select 'label[for=?]', "issue_custom_field_values_#{cf2.id}" do
  1372. assert_select 'span[class=required]'
  1373. end
  1374. end
  1375. def test_get_new_should_not_display_readonly_fields
  1376. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1377. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1378. WorkflowPermission.delete_all
  1379. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
  1380. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
  1381. @request.session[:user_id] = 2
  1382. get :new, :project_id => 1
  1383. assert_response :success
  1384. assert_template 'new'
  1385. assert_select 'input[name=?]', 'issue[start_date]'
  1386. assert_select 'input[name=?]', 'issue[due_date]', 0
  1387. assert_select 'input[name=?]', "issue[custom_field_values][#{cf1.id}]"
  1388. assert_select 'input[name=?]', "issue[custom_field_values][#{cf2.id}]", 0
  1389. end
  1390. def test_get_new_without_tracker_id
  1391. @request.session[:user_id] = 2
  1392. get :new, :project_id => 1
  1393. assert_response :success
  1394. assert_template 'new'
  1395. issue = assigns(:issue)
  1396. assert_not_nil issue
  1397. assert_equal Project.find(1).trackers.first, issue.tracker
  1398. end
  1399. def test_get_new_with_no_default_status_should_display_an_error
  1400. @request.session[:user_id] = 2
  1401. IssueStatus.delete_all
  1402. get :new, :project_id => 1
  1403. assert_response 500
  1404. assert_error_tag :content => /No default issue/
  1405. end
  1406. def test_get_new_with_no_tracker_should_display_an_error
  1407. @request.session[:user_id] = 2
  1408. Tracker.delete_all
  1409. get :new, :project_id => 1
  1410. assert_response 500
  1411. assert_error_tag :content => /No tracker/
  1412. end
  1413. def test_update_form_for_new_issue
  1414. @request.session[:user_id] = 2
  1415. xhr :post, :update_form, :project_id => 1,
  1416. :issue => {:tracker_id => 2,
  1417. :subject => 'This is the test_new issue',
  1418. :description => 'This is the description',
  1419. :priority_id => 5}
  1420. assert_response :success
  1421. assert_template 'update_form'
  1422. assert_template 'form'
  1423. assert_equal 'text/javascript', response.content_type
  1424. issue = assigns(:issue)
  1425. assert_kind_of Issue, issue
  1426. assert_equal 1, issue.project_id
  1427. assert_equal 2, issue.tracker_id
  1428. assert_equal 'This is the test_new issue', issue.subject
  1429. end
  1430. def test_update_form_for_new_issue_should_propose_transitions_based_on_initial_status
  1431. @request.session[:user_id] = 2
  1432. WorkflowTransition.delete_all
  1433. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2)
  1434. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5)
  1435. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 5, :new_status_id => 4)
  1436. xhr :post, :update_form, :project_id => 1,
  1437. :issue => {:tracker_id => 1,
  1438. :status_id => 5,
  1439. :subject => 'This is an issue'}
  1440. assert_equal 5, assigns(:issue).status_id
  1441. assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
  1442. end
  1443. def test_post_create
  1444. @request.session[:user_id] = 2
  1445. assert_difference 'Issue.count' do
  1446. post :create, :project_id => 1,
  1447. :issue => {:tracker_id => 3,
  1448. :status_id => 2,
  1449. :subject => 'This is the test_new issue',
  1450. :description => 'This is the description',
  1451. :priority_id => 5,
  1452. :start_date => '2010-11-07',
  1453. :estimated_hours => '',
  1454. :custom_field_values => {'2' => 'Value for field 2'}}
  1455. end
  1456. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  1457. issue = Issue.find_by_subject('This is the test_new issue')
  1458. assert_not_nil issue
  1459. assert_equal 2, issue.author_id
  1460. assert_equal 3, issue.tracker_id
  1461. assert_equal 2, issue.status_id
  1462. assert_equal Date.parse('2010-11-07'), issue.start_date
  1463. assert_nil issue.estimated_hours
  1464. v = issue.custom_values.where(:custom_field_id => 2).first
  1465. assert_not_nil v
  1466. assert_equal 'Value for field 2', v.value
  1467. end
  1468. def test_post_new_with_group_assignment
  1469. group = Group.find(11)
  1470. project = Project.find(1)
  1471. project.members << Member.new(:principal => group, :roles => [Role.givable.first])
  1472. with_settings :issue_group_assignment => '1' do
  1473. @request.session[:user_id] = 2
  1474. assert_difference 'Issue.count' do
  1475. post :create, :project_id => project.id,
  1476. :issue => {:tracker_id => 3,
  1477. :status_id => 1,
  1478. :subject => 'This is the test_new_with_group_assignment issue',
  1479. :assigned_to_id => group.id}
  1480. end
  1481. end
  1482. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  1483. issue = Issue.find_by_subject('This is the test_new_with_group_assignment issue')
  1484. assert_not_nil issue
  1485. assert_equal group, issue.assigned_to
  1486. end
  1487. def test_post_create_without_start_date_and_default_start_date_is_not_creation_date
  1488. Setting.default_issue_start_date_to_creation_date = 0
  1489. @request.session[:user_id] = 2
  1490. assert_difference 'Issue.count' do
  1491. post :create, :project_id => 1,
  1492. :issue => {:tracker_id => 3,
  1493. :status_id => 2,
  1494. :subject => 'This is the test_new issue',
  1495. :description => 'This is the description',
  1496. :priority_id => 5,
  1497. :estimated_hours => '',
  1498. :custom_field_values => {'2' => 'Value for field 2'}}
  1499. end
  1500. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  1501. issue = Issue.find_by_subject('This is the test_new issue')
  1502. assert_not_nil issue
  1503. assert_nil issue.start_date
  1504. end
  1505. def test_post_create_without_start_date_and_default_start_date_is_creation_date
  1506. Setting.default_issue_start_date_to_creation_date = 1
  1507. @request.session[:user_id] = 2
  1508. assert_difference 'Issue.count' do
  1509. post :create, :project_id => 1,
  1510. :issue => {:tracker_id => 3,
  1511. :status_id => 2,
  1512. :subject => 'This is the test_new issue',
  1513. :description => 'This is the description',
  1514. :priority_id => 5,
  1515. :estimated_hours => '',
  1516. :custom_field_values => {'2' => 'Value for field 2'}}
  1517. end
  1518. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  1519. issue = Issue.find_by_subject('This is the test_new issue')
  1520. assert_not_nil issue
  1521. assert_equal Date.today, issue.start_date
  1522. end
  1523. def test_post_create_and_continue
  1524. @request.session[:user_id] = 2
  1525. assert_difference 'Issue.count' do
  1526. post :create, :project_id => 1,
  1527. :issue => {:tracker_id => 3, :subject => 'This is first issue', :priority_id => 5},
  1528. :continue => ''
  1529. end
  1530. issue = Issue.first(:order => 'id DESC')
  1531. assert_redirected_to :controller => 'issues', :action => 'new', :project_id => 'ecookbook', :issue => {:tracker_id => 3}
  1532. assert_not_nil flash[:notice], "flash was not set"
  1533. assert_include %|<a href="/issues/#{issue.id}" title="This is first issue">##{issue.id}</a>|, flash[:notice], "issue link not found in the flash message"
  1534. end
  1535. def test_post_create_without_custom_fields_param
  1536. @request.session[:user_id] = 2
  1537. assert_difference 'Issue.count' do
  1538. post :create, :project_id => 1,
  1539. :issue => {:tracker_id => 1,
  1540. :subject => 'This is the test_new issue',
  1541. :description => 'This is the description',
  1542. :priority_id => 5}
  1543. end
  1544. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  1545. end
  1546. def test_post_create_with_multi_custom_field
  1547. field = IssueCustomField.find_by_name('Database')
  1548. field.update_attribute(:multiple, true)
  1549. @request.session[:user_id] = 2
  1550. assert_difference 'Issue.count' do
  1551. post :create, :project_id => 1,
  1552. :issue => {:tracker_id => 1,
  1553. :subject => 'This is the test_new issue',
  1554. :description => 'This is the description',
  1555. :priority_id => 5,
  1556. :custom_field_values => {'1' => ['', 'MySQL', 'Oracle']}}
  1557. end
  1558. assert_response 302
  1559. issue = Issue.first(:order => 'id DESC')
  1560. assert_equal ['MySQL', 'Oracle'], issue.custom_field_value(1).sort
  1561. end
  1562. def test_post_create_with_empty_multi_custom_field
  1563. field = IssueCustomField.find_by_name('Database')
  1564. field.update_attribute(:multiple, true)
  1565. @request.session[:user_id] = 2
  1566. assert_difference 'Issue.count' do
  1567. post :create, :project_id => 1,
  1568. :issue => {:tracker_id => 1,
  1569. :subject => 'This is the test_new issue',
  1570. :description => 'This is the description',
  1571. :priority_id => 5,
  1572. :custom_field_values => {'1' => ['']}}
  1573. end
  1574. assert_response 302
  1575. issue = Issue.first(:order => 'id DESC')
  1576. assert_equal [''], issue.custom_field_value(1).sort
  1577. end
  1578. def test_post_create_with_multi_user_custom_field
  1579. field = IssueCustomField.create!(:name => 'Multi user', :field_format => 'user', :multiple => true,
  1580. :tracker_ids => [1], :is_for_all => true)
  1581. @request.session[:user_id] = 2
  1582. assert_difference 'Issue.count' do
  1583. post :create, :project_id => 1,
  1584. :issue => {:tracker_id => 1,
  1585. :subject => 'This is the test_new issue',
  1586. :description => 'This is the description',
  1587. :priority_id => 5,
  1588. :custom_field_values => {field.id.to_s => ['', '2', '3']}}
  1589. end
  1590. assert_response 302
  1591. issue = Issue.first(:order => 'id DESC')
  1592. assert_equal ['2', '3'], issue.custom_field_value(field).sort
  1593. end
  1594. def test_post_create_with_required_custom_field_and_without_custom_fields_param
  1595. field = IssueCustomField.find_by_name('Database')
  1596. field.update_attribute(:is_required, true)
  1597. @request.session[:user_id] = 2
  1598. assert_no_difference 'Issue.count' do
  1599. post :create, :project_id => 1,
  1600. :issue => {:tracker_id => 1,
  1601. :subject => 'This is the test_new issue',
  1602. :description => 'This is the description',
  1603. :priority_id => 5}
  1604. end
  1605. assert_response :success
  1606. assert_template 'new'
  1607. issue = assigns(:issue)
  1608. assert_not_nil issue
  1609. assert_error_tag :content => /Database can&#x27;t be blank/
  1610. end
  1611. def test_create_should_validate_required_fields
  1612. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1613. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1614. WorkflowPermission.delete_all
  1615. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'required')
  1616. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'required')
  1617. @request.session[:user_id] = 2
  1618. assert_no_difference 'Issue.count' do
  1619. post :create, :project_id => 1, :issue => {
  1620. :tracker_id => 2,
  1621. :status_id => 1,
  1622. :subject => 'Test',
  1623. :start_date => '',
  1624. :due_date => '',
  1625. :custom_field_values => {cf1.id.to_s => '', cf2.id.to_s => ''}
  1626. }
  1627. assert_response :success
  1628. assert_template 'new'
  1629. end
  1630. assert_error_tag :content => /Due date can&#x27;t be blank/i
  1631. assert_error_tag :content => /Bar can&#x27;t be blank/i
  1632. end
  1633. def test_create_should_ignore_readonly_fields
  1634. cf1 = IssueCustomField.create!(:name => 'Foo', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1635. cf2 = IssueCustomField.create!(:name => 'Bar', :field_format => 'string', :is_for_all => true, :tracker_ids => [1, 2])
  1636. WorkflowPermission.delete_all
  1637. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => 'due_date', :rule => 'readonly')
  1638. WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2, :role_id => 1, :field_name => cf2.id.to_s, :rule => 'readonly')
  1639. @request.session[:user_id] = 2
  1640. assert_difference 'Issue.count' do
  1641. post :create, :project_id => 1, :issue => {
  1642. :tracker_id => 2,
  1643. :status_id => 1,
  1644. :subject => 'Test',
  1645. :start_date => '2012-07-14',
  1646. :due_date => '2012-07-16',
  1647. :custom_field_values => {cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'}
  1648. }
  1649. assert_response 302
  1650. end
  1651. issue = Issue.first(:order => 'id DESC')
  1652. assert_equal Date.parse('2012-07-14'), issue.start_date
  1653. assert_nil issue.due_date
  1654. assert_equal 'value1', issue.custom_field_value(cf1)
  1655. assert_nil issue.custom_field_value(cf2)
  1656. end
  1657. def test_post_create_with_watchers
  1658. @request.session[:user_id] = 2
  1659. ActionMailer::Base.deliveries.clear
  1660. assert_difference 'Watcher.count', 2 do
  1661. post :create, :project_id => 1,
  1662. :issue => {:tracker_id => 1,
  1663. :subject => 'This is a new issue with watchers',
  1664. :description => 'This is the description',
  1665. :priority_id => 5,
  1666. :watcher_user_ids => ['2', '3']}
  1667. end
  1668. issue = Issue.find_by_subject('This is a new issue with watchers')
  1669. assert_not_nil issue
  1670. assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
  1671. # Watchers added
  1672. assert_equal [2, 3], issue.watcher_user_ids.sort
  1673. assert issue.watched_by?(User.find(3))
  1674. # Watchers notified
  1675. mail = ActionMailer::Base.deliveries.last
  1676. assert_not_nil mail
  1677. assert [mail.bcc, mail.cc].flatten.include?(User.find(3).mail)
  1678. end
  1679. def test_post_create_subissue
  1680. @request.session[:user_id] = 2
  1681. assert_difference 'Issue.count' do
  1682. post :create, :project_id => 1,
  1683. :issue => {:tracker_id => 1,
  1684. :subject => 'This is a child issue',
  1685. :parent_issue_id => '2'}
  1686. assert_response 302
  1687. end
  1688. issue = Issue.order('id DESC').first
  1689. assert_equal Issue.find(2), issue.parent
  1690. end
  1691. def test_post_create_subissue_with_sharp_parent_id
  1692. @request.session[:user_id] = 2
  1693. assert_difference 'Issue.count' do
  1694. post :create, :project_id => 1,
  1695. :issue => {:tracker_id => 1,
  1696. :subject => 'This is a child issue',
  1697. :parent_issue_id => '#2'}
  1698. assert_response 302
  1699. end
  1700. issue = Issue.order('id DESC').first
  1701. assert_equal Issue.find(2), issue.parent
  1702. end
  1703. def test_post_create_subissue_with_non_visible_parent_id_should_not_validate
  1704. @request.session[:user_id] = 2
  1705. assert_no_difference 'Issue.count' do
  1706. post :create, :project_id => 1,
  1707. :issue => {:tracker_id => 1,
  1708. :subject => 'This is a child issue',
  1709. :parent_issue_id => '4'}
  1710. assert_response :success
  1711. assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '4'
  1712. assert_error_tag :content => /Parent task is invalid/i
  1713. end
  1714. end
  1715. def test_post_create_subissue_with_non_numeric_parent_id_should_not_validate
  1716. @request.session[:user_id] = 2
  1717. assert_no_difference 'Issue.count' do
  1718. post :create, :project_id => 1,
  1719. :issue => {:tracker_id => 1,
  1720. :subject => 'This is a child issue',
  1721. :parent_issue_id => '01ABC'}
  1722. assert_response :success
  1723. assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', '01ABC'
  1724. assert_error_tag :content => /Parent task is invalid/i
  1725. end
  1726. end
  1727. def test_post_create_private
  1728. @request.session[:user_id] = 2
  1729. assert_difference 'Issue.count' do
  1730. post :create, :project_id => 1,
  1731. :issue => {:tracker_id => 1,
  1732. :subject => 'This is a private issue',
  1733. :is_private => '1'}
  1734. end
  1735. issue = Issue.first(:order => 'id DESC')
  1736. assert issue.is_private?
  1737. end
  1738. def test_post_create_private_with_set_own_issues_private_permission
  1739. role = Role.find(1)
  1740. role.remove_permission! :set_issues_private
  1741. role.add_permission! :set_own_issues_private
  1742. @request.session[:user_id] = 2
  1743. assert_difference 'Issue.count' do
  1744. post :create, :project_id => 1,
  1745. :issue => {:tracker_id => 1,
  1746. :subject => 'This is a private issue',
  1747. :is_private => '1'}
  1748. end
  1749. issue = Issue.first(:order => 'id DESC')
  1750. assert issue.is_private?
  1751. end
  1752. def test_post_create_should_send_a_notification
  1753. ActionMailer::Base.deliveries.clear
  1754. @request.session[:user_id] = 2
  1755. assert_difference 'Issue.count' do
  1756. post :create, :project_id => 1,
  1757. :issue => {:tracker_id => 3,
  1758. :subject => 'This is the test_new issue',
  1759. :description => 'This is the description',
  1760. :priority_id => 5,
  1761. :estimated_hours => '',
  1762. :custom_field_values => {'2' => 'Value for field 2'}}
  1763. end
  1764. assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
  1765. assert_equal 1, ActionMailer::Base.deliveries.size
  1766. end
  1767. def test_post_create_should_preserve_fields_values_on_validation_failure
  1768. @request.session[:user_id] = 2
  1769. post :create, :project_id => 1,
  1770. :issue => {:tracker_id => 1,
  1771. # empty subject
  1772. :subject => '',
  1773. :description => 'This is a description',
  1774. :priority_id => 6,
  1775. :custom_field_values => {'1' => 'Oracle', '2' => 'Value for field 2'}}
  1776. assert_response :success
  1777. assert_template 'new'
  1778. assert_select 'textarea[name=?]', 'issue[description]', :text => 'This is a description'
  1779. assert_select 'select[name=?]', 'issue[priority_id]' do
  1780. assert_select 'option[value=6][selected=selected]', :text => 'High'
  1781. end
  1782. # Custom fields
  1783. assert_select 'select[name=?]', 'issue[custom_field_values][1]' do
  1784. assert_select 'option[value=Oracle][selected=selected]', :text => 'Oracle'
  1785. end
  1786. assert_select 'input[name=?][value=?]', 'issue[custom_field_values][2]', 'Value for field 2'
  1787. end
  1788. def test_post_create_with_failure_should_preserve_watchers
  1789. assert !User.find(8).member_of?(Project.find(1))
  1790. @request.session[:user_id] = 2
  1791. post :create, :project_id => 1,
  1792. :issue => {:tracker_id => 1,
  1793. :watcher_user_ids => ['3', '8']}
  1794. assert_response :success
  1795. assert_template 'new'
  1796. assert_select 'input[name=?][value=2]:not(checked)', 'issue[watcher_user_ids][]'
  1797. assert_select 'input[name=?][value=3][checked=checked]', 'issue[watcher_user_ids][]'
  1798. assert_select 'input[name=?][value=8][checked=checked]', 'issue[watcher_user_ids][]'
  1799. end
  1800. def test_post_create_should_ignore_non_safe_attributes
  1801. @request.session[:user_id] = 2
  1802. assert_nothing_raised do
  1803. post :create, :project_id => 1, :issue => { :tracker => "A param can not be a Tracker" }
  1804. end
  1805. end
  1806. def test_post_create_with_attachment
  1807. set_tmp_attachments_directory
  1808. @request.session[:user_id] = 2
  1809. assert_difference 'Issue.count' do
  1810. assert_difference 'Attachment.count' do
  1811. post :create, :project_id => 1,
  1812. :issue => { :tracker_id => '1', :subject => 'With attachment' },
  1813. :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
  1814. end
  1815. end
  1816. issue = Issue.first(:order => 'id DESC')
  1817. attachment = Attachment.first(:order => 'id DESC')
  1818. assert_equal issue, attachment.container
  1819. assert_equal 2, attachment.author_id
  1820. assert_equal 'testfile.txt', attachment.filename
  1821. assert_equal 'text/plain', attachment.content_type
  1822. assert_equal 'test file', attachment.description
  1823. assert_equal 59, attachment.filesize
  1824. assert File.exists?(attachment.diskfile)
  1825. assert_equal 59, File.size(attachment.diskfile)
  1826. end
  1827. def test_post_create_with_failure_should_save_attachments
  1828. set_tmp_attachments_directory
  1829. @request.session[:user_id] = 2
  1830. assert_no_difference 'Issue.count' do
  1831. assert_difference 'Attachment.count' do
  1832. post :create, :project_id => 1,
  1833. :issue => { :tracker_id => '1', :subject => '' },
  1834. :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
  1835. assert_response :success
  1836. assert_template 'new'
  1837. end
  1838. end
  1839. attachment = Attachment.first(:order => 'id DESC')
  1840. assert_equal 'testfile.txt', attachment.filename
  1841. assert File.exists?(attachment.diskfile)
  1842. assert_nil attachment.container
  1843. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  1844. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  1845. end
  1846. def test_post_create_with_failure_should_keep_saved_attachments
  1847. set_tmp_attachments_directory
  1848. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  1849. @request.session[:user_id] = 2
  1850. assert_no_difference 'Issue.count' do
  1851. assert_no_difference 'Attachment.count' do
  1852. post :create, :project_id => 1,
  1853. :issue => { :tracker_id => '1', :subject => '' },
  1854. :attachments => {'p0' => {'token' => attachment.token}}
  1855. assert_response :success
  1856. assert_template 'new'
  1857. end
  1858. end
  1859. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  1860. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  1861. end
  1862. def test_post_create_should_attach_saved_attachments
  1863. set_tmp_attachments_directory
  1864. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  1865. @request.session[:user_id] = 2
  1866. assert_difference 'Issue.count' do
  1867. assert_no_difference 'Attachment.count' do
  1868. post :create, :project_id => 1,
  1869. :issue => { :tracker_id => '1', :subject => 'Saved attachments' },
  1870. :attachments => {'p0' => {'token' => attachment.token}}
  1871. assert_response 302
  1872. end
  1873. end
  1874. issue = Issue.first(:order => 'id DESC')
  1875. assert_equal 1, issue.attachments.count
  1876. attachment.reload
  1877. assert_equal issue, attachment.container
  1878. end
  1879. context "without workflow privilege" do
  1880. setup do
  1881. WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
  1882. Role.anonymous.add_permission! :add_issues, :add_issue_notes
  1883. end
  1884. context "#new" do
  1885. should "propose default status only" do
  1886. get :new, :project_id => 1
  1887. assert_response :success
  1888. assert_template 'new'
  1889. assert_select 'select[name=?]', 'issue[status_id]' do
  1890. assert_select 'option', 1
  1891. assert_select 'option[value=?]', IssueStatus.default.id.to_s
  1892. end
  1893. end
  1894. should "accept default status" do
  1895. assert_difference 'Issue.count' do
  1896. post :create, :project_id => 1,
  1897. :issue => {:tracker_id => 1,
  1898. :subject => 'This is an issue',
  1899. :status_id => 1}
  1900. end
  1901. issue = Issue.last(:order => 'id')
  1902. assert_equal IssueStatus.default, issue.status
  1903. end
  1904. should "ignore unauthorized status" do
  1905. assert_difference 'Issue.count' do
  1906. post :create, :project_id => 1,
  1907. :issue => {:tracker_id => 1,
  1908. :subject => 'This is an issue',
  1909. :status_id => 3}
  1910. end
  1911. issue = Issue.last(:order => 'id')
  1912. assert_equal IssueStatus.default, issue.status
  1913. end
  1914. end
  1915. context "#update" do
  1916. should "ignore status change" do
  1917. assert_difference 'Journal.count' do
  1918. put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
  1919. end
  1920. assert_equal 1, Issue.find(1).status_id
  1921. end
  1922. should "ignore attributes changes" do
  1923. assert_difference 'Journal.count' do
  1924. put :update, :id => 1, :issue => {:subject => 'changed', :assigned_to_id => 2, :notes => 'just trying'}
  1925. end
  1926. issue = Issue.find(1)
  1927. assert_equal "Can't print recipes", issue.subject
  1928. assert_nil issue.assigned_to
  1929. end
  1930. end
  1931. end
  1932. context "with workflow privilege" do
  1933. setup do
  1934. WorkflowTransition.delete_all(["role_id = ?", Role.anonymous.id])
  1935. WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
  1936. WorkflowTransition.create!(:role => Role.anonymous, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
  1937. Role.anonymous.add_permission! :add_issues, :add_issue_notes
  1938. end
  1939. context "#update" do
  1940. should "accept authorized status" do
  1941. assert_difference 'Journal.count' do
  1942. put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
  1943. end
  1944. assert_equal 3, Issue.find(1).status_id
  1945. end
  1946. should "ignore unauthorized status" do
  1947. assert_difference 'Journal.count' do
  1948. put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
  1949. end
  1950. assert_equal 1, Issue.find(1).status_id
  1951. end
  1952. should "accept authorized attributes changes" do
  1953. assert_difference 'Journal.count' do
  1954. put :update, :id => 1, :issue => {:assigned_to_id => 2, :notes => 'just trying'}
  1955. end
  1956. issue = Issue.find(1)
  1957. assert_equal 2, issue.assigned_to_id
  1958. end
  1959. should "ignore unauthorized attributes changes" do
  1960. assert_difference 'Journal.count' do
  1961. put :update, :id => 1, :issue => {:subject => 'changed', :notes => 'just trying'}
  1962. end
  1963. issue = Issue.find(1)
  1964. assert_equal "Can't print recipes", issue.subject
  1965. end
  1966. end
  1967. context "and :edit_issues permission" do
  1968. setup do
  1969. Role.anonymous.add_permission! :add_issues, :edit_issues
  1970. end
  1971. should "accept authorized status" do
  1972. assert_difference 'Journal.count' do
  1973. put :update, :id => 1, :issue => {:status_id => 3, :notes => 'just trying'}
  1974. end
  1975. assert_equal 3, Issue.find(1).status_id
  1976. end
  1977. should "ignore unauthorized status" do
  1978. assert_difference 'Journal.count' do
  1979. put :update, :id => 1, :issue => {:status_id => 2, :notes => 'just trying'}
  1980. end
  1981. assert_equal 1, Issue.find(1).status_id
  1982. end
  1983. should "accept authorized attributes changes" do
  1984. assert_difference 'Journal.count' do
  1985. put :update, :id => 1, :issue => {:subject => 'changed', :assigned_to_id => 2, :notes => 'just trying'}
  1986. end
  1987. issue = Issue.find(1)
  1988. assert_equal "changed", issue.subject
  1989. assert_equal 2, issue.assigned_to_id
  1990. end
  1991. end
  1992. end
  1993. def test_new_as_copy
  1994. @request.session[:user_id] = 2
  1995. get :new, :project_id => 1, :copy_from => 1
  1996. assert_response :success
  1997. assert_template 'new'
  1998. assert_not_nil assigns(:issue)
  1999. orig = Issue.find(1)
  2000. assert_equal 1, assigns(:issue).project_id
  2001. assert_equal orig.subject, assigns(:issue).subject
  2002. assert assigns(:issue).copy?
  2003. assert_select 'form[id=issue-form][action=/projects/ecookbook/issues]' do
  2004. assert_select 'select[name=?]', 'issue[project_id]' do
  2005. assert_select 'option[value=1][selected=selected]', :text => 'eCookbook'
  2006. assert_select 'option[value=2]:not([selected])', :text => 'OnlineStore'
  2007. end
  2008. assert_select 'input[name=copy_from][value=1]'
  2009. end
  2010. # "New issue" menu item should not link to copy
  2011. assert_select '#main-menu a.new-issue[href=/projects/ecookbook/issues/new]'
  2012. end
  2013. def test_new_as_copy_with_attachments_should_show_copy_attachments_checkbox
  2014. @request.session[:user_id] = 2
  2015. issue = Issue.find(3)
  2016. assert issue.attachments.count > 0
  2017. get :new, :project_id => 1, :copy_from => 3
  2018. assert_select 'input[name=copy_attachments][type=checkbox][checked=checked][value=1]'
  2019. end
  2020. def test_new_as_copy_without_attachments_should_not_show_copy_attachments_checkbox
  2021. @request.session[:user_id] = 2
  2022. issue = Issue.find(3)
  2023. issue.attachments.delete_all
  2024. get :new, :project_id => 1, :copy_from => 3
  2025. assert_select 'input[name=copy_attachments]', 0
  2026. end
  2027. def test_new_as_copy_with_subtasks_should_show_copy_subtasks_checkbox
  2028. @request.session[:user_id] = 2
  2029. issue = Issue.generate_with_descendants!
  2030. get :new, :project_id => 1, :copy_from => issue.id
  2031. assert_select 'input[type=checkbox][name=copy_subtasks][checked=checked][value=1]'
  2032. end
  2033. def test_new_as_copy_with_invalid_issue_should_respond_with_404
  2034. @request.session[:user_id] = 2
  2035. get :new, :project_id => 1, :copy_from => 99999
  2036. assert_response 404
  2037. end
  2038. def test_create_as_copy_on_different_project
  2039. @request.session[:user_id] = 2
  2040. assert_difference 'Issue.count' do
  2041. post :create, :project_id => 1, :copy_from => 1,
  2042. :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
  2043. assert_not_nil assigns(:issue)
  2044. assert assigns(:issue).copy?
  2045. end
  2046. issue = Issue.first(:order => 'id DESC')
  2047. assert_redirected_to "/issues/#{issue.id}"
  2048. assert_equal 2, issue.project_id
  2049. assert_equal 3, issue.tracker_id
  2050. assert_equal 'Copy', issue.subject
  2051. end
  2052. def test_create_as_copy_should_copy_attachments
  2053. @request.session[:user_id] = 2
  2054. issue = Issue.find(3)
  2055. count = issue.attachments.count
  2056. assert count > 0
  2057. assert_difference 'Issue.count' do
  2058. assert_difference 'Attachment.count', count do
  2059. assert_no_difference 'Journal.count' do
  2060. post :create, :project_id => 1, :copy_from => 3,
  2061. :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'},
  2062. :copy_attachments => '1'
  2063. end
  2064. end
  2065. end
  2066. copy = Issue.first(:order => 'id DESC')
  2067. assert_equal count, copy.attachments.count
  2068. assert_equal issue.attachments.map(&:filename).sort, copy.attachments.map(&:filename).sort
  2069. end
  2070. def test_create_as_copy_without_copy_attachments_option_should_not_copy_attachments
  2071. @request.session[:user_id] = 2
  2072. issue = Issue.find(3)
  2073. count = issue.attachments.count
  2074. assert count > 0
  2075. assert_difference 'Issue.count' do
  2076. assert_no_difference 'Attachment.count' do
  2077. assert_no_difference 'Journal.count' do
  2078. post :create, :project_id => 1, :copy_from => 3,
  2079. :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'}
  2080. end
  2081. end
  2082. end
  2083. copy = Issue.first(:order => 'id DESC')
  2084. assert_equal 0, copy.attachments.count
  2085. end
  2086. def test_create_as_copy_with_attachments_should_add_new_files
  2087. @request.session[:user_id] = 2
  2088. issue = Issue.find(3)
  2089. count = issue.attachments.count
  2090. assert count > 0
  2091. assert_difference 'Issue.count' do
  2092. assert_difference 'Attachment.count', count + 1 do
  2093. assert_no_difference 'Journal.count' do
  2094. post :create, :project_id => 1, :copy_from => 3,
  2095. :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with attachments'},
  2096. :copy_attachments => '1',
  2097. :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
  2098. end
  2099. end
  2100. end
  2101. copy = Issue.first(:order => 'id DESC')
  2102. assert_equal count + 1, copy.attachments.count
  2103. end
  2104. def test_create_as_copy_should_add_relation_with_copied_issue
  2105. @request.session[:user_id] = 2
  2106. assert_difference 'Issue.count' do
  2107. assert_difference 'IssueRelation.count' do
  2108. post :create, :project_id => 1, :copy_from => 1,
  2109. :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
  2110. end
  2111. end
  2112. copy = Issue.first(:order => 'id DESC')
  2113. assert_equal 1, copy.relations.size
  2114. end
  2115. def test_create_as_copy_should_copy_subtasks
  2116. @request.session[:user_id] = 2
  2117. issue = Issue.generate_with_descendants!
  2118. count = issue.descendants.count
  2119. assert_difference 'Issue.count', count+1 do
  2120. assert_no_difference 'Journal.count' do
  2121. post :create, :project_id => 1, :copy_from => issue.id,
  2122. :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with subtasks'},
  2123. :copy_subtasks => '1'
  2124. end
  2125. end
  2126. copy = Issue.where(:parent_id => nil).first(:order => 'id DESC')
  2127. assert_equal count, copy.descendants.count
  2128. assert_equal issue.descendants.map(&:subject).sort, copy.descendants.map(&:subject).sort
  2129. end
  2130. def test_create_as_copy_without_copy_subtasks_option_should_not_copy_subtasks
  2131. @request.session[:user_id] = 2
  2132. issue = Issue.generate_with_descendants!
  2133. assert_difference 'Issue.count', 1 do
  2134. assert_no_difference 'Journal.count' do
  2135. post :create, :project_id => 1, :copy_from => 3,
  2136. :issue => {:project_id => '1', :tracker_id => '3', :status_id => '1', :subject => 'Copy with subtasks'}
  2137. end
  2138. end
  2139. copy = Issue.where(:parent_id => nil).first(:order => 'id DESC')
  2140. assert_equal 0, copy.descendants.count
  2141. end
  2142. def test_create_as_copy_with_failure
  2143. @request.session[:user_id] = 2
  2144. post :create, :project_id => 1, :copy_from => 1,
  2145. :issue => {:project_id => '2', :tracker_id => '3', :status_id => '1', :subject => ''}
  2146. assert_response :success
  2147. assert_template 'new'
  2148. assert_not_nil assigns(:issue)
  2149. assert assigns(:issue).copy?
  2150. assert_select 'form#issue-form[action=/projects/ecookbook/issues]' do
  2151. assert_select 'select[name=?]', 'issue[project_id]' do
  2152. assert_select 'option[value=1]:not([selected])', :text => 'eCookbook'
  2153. assert_select 'option[value=2][selected=selected]', :text => 'OnlineStore'
  2154. end
  2155. assert_select 'input[name=copy_from][value=1]'
  2156. end
  2157. end
  2158. def test_create_as_copy_on_project_without_permission_should_ignore_target_project
  2159. @request.session[:user_id] = 2
  2160. assert !User.find(2).member_of?(Project.find(4))
  2161. assert_difference 'Issue.count' do
  2162. post :create, :project_id => 1, :copy_from => 1,
  2163. :issue => {:project_id => '4', :tracker_id => '3', :status_id => '1', :subject => 'Copy'}
  2164. end
  2165. issue = Issue.first(:order => 'id DESC')
  2166. assert_equal 1, issue.project_id
  2167. end
  2168. def test_get_edit
  2169. @request.session[:user_id] = 2
  2170. get :edit, :id => 1
  2171. assert_response :success
  2172. assert_template 'edit'
  2173. assert_not_nil assigns(:issue)
  2174. assert_equal Issue.find(1), assigns(:issue)
  2175. # Be sure we don't display inactive IssuePriorities
  2176. assert ! IssuePriority.find(15).active?
  2177. assert_select 'select[name=?]', 'issue[priority_id]' do
  2178. assert_select 'option[value=15]', 0
  2179. end
  2180. end
  2181. def test_get_edit_should_display_the_time_entry_form_with_log_time_permission
  2182. @request.session[:user_id] = 2
  2183. Role.find_by_name('Manager').update_attribute :permissions, [:view_issues, :edit_issues, :log_time]
  2184. get :edit, :id => 1
  2185. assert_select 'input[name=?]', 'time_entry[hours]'
  2186. end
  2187. def test_get_edit_should_not_display_the_time_entry_form_without_log_time_permission
  2188. @request.session[:user_id] = 2
  2189. Role.find_by_name('Manager').remove_permission! :log_time
  2190. get :edit, :id => 1
  2191. assert_select 'input[name=?]', 'time_entry[hours]', 0
  2192. end
  2193. def test_get_edit_with_params
  2194. @request.session[:user_id] = 2
  2195. get :edit, :id => 1, :issue => { :status_id => 5, :priority_id => 7 },
  2196. :time_entry => { :hours => '2.5', :comments => 'test_get_edit_with_params', :activity_id => 10 }
  2197. assert_response :success
  2198. assert_template 'edit'
  2199. issue = assigns(:issue)
  2200. assert_not_nil issue
  2201. assert_equal 5, issue.status_id
  2202. assert_select 'select[name=?]', 'issue[status_id]' do
  2203. assert_select 'option[value=5][selected=selected]', :text => 'Closed'
  2204. end
  2205. assert_equal 7, issue.priority_id
  2206. assert_select 'select[name=?]', 'issue[priority_id]' do
  2207. assert_select 'option[value=7][selected=selected]', :text => 'Urgent'
  2208. end
  2209. assert_select 'input[name=?][value=2.5]', 'time_entry[hours]'
  2210. assert_select 'select[name=?]', 'time_entry[activity_id]' do
  2211. assert_select 'option[value=10][selected=selected]', :text => 'Development'
  2212. end
  2213. assert_select 'input[name=?][value=test_get_edit_with_params]', 'time_entry[comments]'
  2214. end
  2215. def test_get_edit_with_multi_custom_field
  2216. field = CustomField.find(1)
  2217. field.update_attribute :multiple, true
  2218. issue = Issue.find(1)
  2219. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  2220. issue.save!
  2221. @request.session[:user_id] = 2
  2222. get :edit, :id => 1
  2223. assert_response :success
  2224. assert_template 'edit'
  2225. assert_select 'select[name=?][multiple=multiple]', 'issue[custom_field_values][1][]' do
  2226. assert_select 'option', 3
  2227. assert_select 'option[value=MySQL][selected=selected]'
  2228. assert_select 'option[value=Oracle][selected=selected]'
  2229. assert_select 'option[value=PostgreSQL]:not([selected])'
  2230. end
  2231. end
  2232. def test_update_form_for_existing_issue
  2233. @request.session[:user_id] = 2
  2234. xhr :put, :update_form, :project_id => 1,
  2235. :id => 1,
  2236. :issue => {:tracker_id => 2,
  2237. :subject => 'This is the test_new issue',
  2238. :description => 'This is the description',
  2239. :priority_id => 5}
  2240. assert_response :success
  2241. assert_equal 'text/javascript', response.content_type
  2242. assert_template 'update_form'
  2243. assert_template 'form'
  2244. issue = assigns(:issue)
  2245. assert_kind_of Issue, issue
  2246. assert_equal 1, issue.id
  2247. assert_equal 1, issue.project_id
  2248. assert_equal 2, issue.tracker_id
  2249. assert_equal 'This is the test_new issue', issue.subject
  2250. end
  2251. def test_update_form_for_existing_issue_should_keep_issue_author
  2252. @request.session[:user_id] = 3
  2253. xhr :put, :update_form, :project_id => 1, :id => 1, :issue => {:subject => 'Changed'}
  2254. assert_response :success
  2255. assert_equal 'text/javascript', response.content_type
  2256. issue = assigns(:issue)
  2257. assert_equal User.find(2), issue.author
  2258. assert_equal 2, issue.author_id
  2259. assert_not_equal User.current, issue.author
  2260. end
  2261. def test_update_form_for_existing_issue_should_propose_transitions_based_on_initial_status
  2262. @request.session[:user_id] = 2
  2263. WorkflowTransition.delete_all
  2264. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
  2265. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
  2266. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 5, :new_status_id => 4)
  2267. xhr :put, :update_form, :project_id => 1,
  2268. :id => 2,
  2269. :issue => {:tracker_id => 2,
  2270. :status_id => 5,
  2271. :subject => 'This is an issue'}
  2272. assert_equal 5, assigns(:issue).status_id
  2273. assert_equal [1,2,5], assigns(:allowed_statuses).map(&:id).sort
  2274. end
  2275. def test_update_form_for_existing_issue_with_project_change
  2276. @request.session[:user_id] = 2
  2277. xhr :put, :update_form, :project_id => 1,
  2278. :id => 1,
  2279. :issue => {:project_id => 2,
  2280. :tracker_id => 2,
  2281. :subject => 'This is the test_new issue',
  2282. :description => 'This is the description',
  2283. :priority_id => 5}
  2284. assert_response :success
  2285. assert_template 'form'
  2286. issue = assigns(:issue)
  2287. assert_kind_of Issue, issue
  2288. assert_equal 1, issue.id
  2289. assert_equal 2, issue.project_id
  2290. assert_equal 2, issue.tracker_id
  2291. assert_equal 'This is the test_new issue', issue.subject
  2292. end
  2293. def test_put_update_without_custom_fields_param
  2294. @request.session[:user_id] = 2
  2295. ActionMailer::Base.deliveries.clear
  2296. issue = Issue.find(1)
  2297. assert_equal '125', issue.custom_value_for(2).value
  2298. old_subject = issue.subject
  2299. new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
  2300. assert_difference('Journal.count') do
  2301. assert_difference('JournalDetail.count', 2) do
  2302. put :update, :id => 1, :issue => {:subject => new_subject,
  2303. :priority_id => '6',
  2304. :category_id => '1' # no change
  2305. }
  2306. end
  2307. end
  2308. assert_redirected_to :action => 'show', :id => '1'
  2309. issue.reload
  2310. assert_equal new_subject, issue.subject
  2311. # Make sure custom fields were not cleared
  2312. assert_equal '125', issue.custom_value_for(2).value
  2313. mail = ActionMailer::Base.deliveries.last
  2314. assert_not_nil mail
  2315. assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
  2316. assert_mail_body_match "Subject changed from #{old_subject} to #{new_subject}", mail
  2317. end
  2318. def test_put_update_with_project_change
  2319. @request.session[:user_id] = 2
  2320. ActionMailer::Base.deliveries.clear
  2321. assert_difference('Journal.count') do
  2322. assert_difference('JournalDetail.count', 3) do
  2323. put :update, :id => 1, :issue => {:project_id => '2',
  2324. :tracker_id => '1', # no change
  2325. :priority_id => '6',
  2326. :category_id => '3'
  2327. }
  2328. end
  2329. end
  2330. assert_redirected_to :action => 'show', :id => '1'
  2331. issue = Issue.find(1)
  2332. assert_equal 2, issue.project_id
  2333. assert_equal 1, issue.tracker_id
  2334. assert_equal 6, issue.priority_id
  2335. assert_equal 3, issue.category_id
  2336. mail = ActionMailer::Base.deliveries.last
  2337. assert_not_nil mail
  2338. assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
  2339. assert_mail_body_match "Project changed from eCookbook to OnlineStore", mail
  2340. end
  2341. def test_put_update_with_tracker_change
  2342. @request.session[:user_id] = 2
  2343. ActionMailer::Base.deliveries.clear
  2344. assert_difference('Journal.count') do
  2345. assert_difference('JournalDetail.count', 2) do
  2346. put :update, :id => 1, :issue => {:project_id => '1',
  2347. :tracker_id => '2',
  2348. :priority_id => '6'
  2349. }
  2350. end
  2351. end
  2352. assert_redirected_to :action => 'show', :id => '1'
  2353. issue = Issue.find(1)
  2354. assert_equal 1, issue.project_id
  2355. assert_equal 2, issue.tracker_id
  2356. assert_equal 6, issue.priority_id
  2357. assert_equal 1, issue.category_id
  2358. mail = ActionMailer::Base.deliveries.last
  2359. assert_not_nil mail
  2360. assert mail.subject.starts_with?("[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}]")
  2361. assert_mail_body_match "Tracker changed from Bug to Feature request", mail
  2362. end
  2363. def test_put_update_with_custom_field_change
  2364. @request.session[:user_id] = 2
  2365. issue = Issue.find(1)
  2366. assert_equal '125', issue.custom_value_for(2).value
  2367. assert_difference('Journal.count') do
  2368. assert_difference('JournalDetail.count', 3) do
  2369. put :update, :id => 1, :issue => {:subject => 'Custom field change',
  2370. :priority_id => '6',
  2371. :category_id => '1', # no change
  2372. :custom_field_values => { '2' => 'New custom value' }
  2373. }
  2374. end
  2375. end
  2376. assert_redirected_to :action => 'show', :id => '1'
  2377. issue.reload
  2378. assert_equal 'New custom value', issue.custom_value_for(2).value
  2379. mail = ActionMailer::Base.deliveries.last
  2380. assert_not_nil mail
  2381. assert_mail_body_match "Searchable field changed from 125 to New custom value", mail
  2382. end
  2383. def test_put_update_with_multi_custom_field_change
  2384. field = CustomField.find(1)
  2385. field.update_attribute :multiple, true
  2386. issue = Issue.find(1)
  2387. issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
  2388. issue.save!
  2389. @request.session[:user_id] = 2
  2390. assert_difference('Journal.count') do
  2391. assert_difference('JournalDetail.count', 3) do
  2392. put :update, :id => 1,
  2393. :issue => {
  2394. :subject => 'Custom field change',
  2395. :custom_field_values => { '1' => ['', 'Oracle', 'PostgreSQL'] }
  2396. }
  2397. end
  2398. end
  2399. assert_redirected_to :action => 'show', :id => '1'
  2400. assert_equal ['Oracle', 'PostgreSQL'], Issue.find(1).custom_field_value(1).sort
  2401. end
  2402. def test_put_update_with_status_and_assignee_change
  2403. issue = Issue.find(1)
  2404. assert_equal 1, issue.status_id
  2405. @request.session[:user_id] = 2
  2406. assert_difference('TimeEntry.count', 0) do
  2407. put :update,
  2408. :id => 1,
  2409. :issue => { :status_id => 2, :assigned_to_id => 3, :notes => 'Assigned to dlopper' },
  2410. :time_entry => { :hours => '', :comments => '', :activity_id => TimeEntryActivity.first }
  2411. end
  2412. assert_redirected_to :action => 'show', :id => '1'
  2413. issue.reload
  2414. assert_equal 2, issue.status_id
  2415. j = Journal.order('id DESC').first
  2416. assert_equal 'Assigned to dlopper', j.notes
  2417. assert_equal 2, j.details.size
  2418. mail = ActionMailer::Base.deliveries.last
  2419. assert_mail_body_match "Status changed from New to Assigned", mail
  2420. # subject should contain the new status
  2421. assert mail.subject.include?("(#{ IssueStatus.find(2).name })")
  2422. end
  2423. def test_put_update_with_note_only
  2424. notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
  2425. # anonymous user
  2426. put :update,
  2427. :id => 1,
  2428. :issue => { :notes => notes }
  2429. assert_redirected_to :action => 'show', :id => '1'
  2430. j = Journal.order('id DESC').first
  2431. assert_equal notes, j.notes
  2432. assert_equal 0, j.details.size
  2433. assert_equal User.anonymous, j.user
  2434. mail = ActionMailer::Base.deliveries.last
  2435. assert_mail_body_match notes, mail
  2436. end
  2437. def test_put_update_with_private_note_only
  2438. notes = 'Private note'
  2439. @request.session[:user_id] = 2
  2440. assert_difference 'Journal.count' do
  2441. put :update, :id => 1, :issue => {:notes => notes, :private_notes => '1'}
  2442. assert_redirected_to :action => 'show', :id => '1'
  2443. end
  2444. j = Journal.order('id DESC').first
  2445. assert_equal notes, j.notes
  2446. assert_equal true, j.private_notes
  2447. end
  2448. def test_put_update_with_private_note_and_changes
  2449. notes = 'Private note'
  2450. @request.session[:user_id] = 2
  2451. assert_difference 'Journal.count', 2 do
  2452. put :update, :id => 1, :issue => {:subject => 'New subject', :notes => notes, :private_notes => '1'}
  2453. assert_redirected_to :action => 'show', :id => '1'
  2454. end
  2455. j = Journal.order('id DESC').first
  2456. assert_equal notes, j.notes
  2457. assert_equal true, j.private_notes
  2458. assert_equal 0, j.details.count
  2459. j = Journal.order('id DESC').offset(1).first
  2460. assert_nil j.notes
  2461. assert_equal false, j.private_notes
  2462. assert_equal 1, j.details.count
  2463. end
  2464. def test_put_update_with_note_and_spent_time
  2465. @request.session[:user_id] = 2
  2466. spent_hours_before = Issue.find(1).spent_hours
  2467. assert_difference('TimeEntry.count') do
  2468. put :update,
  2469. :id => 1,
  2470. :issue => { :notes => '2.5 hours added' },
  2471. :time_entry => { :hours => '2.5', :comments => 'test_put_update_with_note_and_spent_time', :activity_id => TimeEntryActivity.first.id }
  2472. end
  2473. assert_redirected_to :action => 'show', :id => '1'
  2474. issue = Issue.find(1)
  2475. j = Journal.order('id DESC').first
  2476. assert_equal '2.5 hours added', j.notes
  2477. assert_equal 0, j.details.size
  2478. t = issue.time_entries.find_by_comments('test_put_update_with_note_and_spent_time')
  2479. assert_not_nil t
  2480. assert_equal 2.5, t.hours
  2481. assert_equal spent_hours_before + 2.5, issue.spent_hours
  2482. end
  2483. def test_put_update_should_preserve_parent_issue_even_if_not_visible
  2484. parent = Issue.generate!(:project_id => 1, :is_private => true)
  2485. issue = Issue.generate!(:parent_issue_id => parent.id)
  2486. assert !parent.visible?(User.find(3))
  2487. @request.session[:user_id] = 3
  2488. get :edit, :id => issue.id
  2489. assert_select 'input[name=?][value=?]', 'issue[parent_issue_id]', parent.id.to_s
  2490. put :update, :id => issue.id, :issue => {:subject => 'New subject', :parent_issue_id => parent.id.to_s}
  2491. assert_response 302
  2492. assert_equal parent, issue.parent
  2493. end
  2494. def test_put_update_with_attachment_only
  2495. set_tmp_attachments_directory
  2496. # Delete all fixtured journals, a race condition can occur causing the wrong
  2497. # journal to get fetched in the next find.
  2498. Journal.delete_all
  2499. # anonymous user
  2500. assert_difference 'Attachment.count' do
  2501. put :update, :id => 1,
  2502. :issue => {:notes => ''},
  2503. :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
  2504. end
  2505. assert_redirected_to :action => 'show', :id => '1'
  2506. j = Issue.find(1).journals.reorder('id DESC').first
  2507. assert j.notes.blank?
  2508. assert_equal 1, j.details.size
  2509. assert_equal 'testfile.txt', j.details.first.value
  2510. assert_equal User.anonymous, j.user
  2511. attachment = Attachment.first(:order => 'id DESC')
  2512. assert_equal Issue.find(1), attachment.container
  2513. assert_equal User.anonymous, attachment.author
  2514. assert_equal 'testfile.txt', attachment.filename
  2515. assert_equal 'text/plain', attachment.content_type
  2516. assert_equal 'test file', attachment.description
  2517. assert_equal 59, attachment.filesize
  2518. assert File.exists?(attachment.diskfile)
  2519. assert_equal 59, File.size(attachment.diskfile)
  2520. mail = ActionMailer::Base.deliveries.last
  2521. assert_mail_body_match 'testfile.txt', mail
  2522. end
  2523. def test_put_update_with_failure_should_save_attachments
  2524. set_tmp_attachments_directory
  2525. @request.session[:user_id] = 2
  2526. assert_no_difference 'Journal.count' do
  2527. assert_difference 'Attachment.count' do
  2528. put :update, :id => 1,
  2529. :issue => { :subject => '' },
  2530. :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain'), 'description' => 'test file'}}
  2531. assert_response :success
  2532. assert_template 'edit'
  2533. end
  2534. end
  2535. attachment = Attachment.first(:order => 'id DESC')
  2536. assert_equal 'testfile.txt', attachment.filename
  2537. assert File.exists?(attachment.diskfile)
  2538. assert_nil attachment.container
  2539. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  2540. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  2541. end
  2542. def test_put_update_with_failure_should_keep_saved_attachments
  2543. set_tmp_attachments_directory
  2544. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  2545. @request.session[:user_id] = 2
  2546. assert_no_difference 'Journal.count' do
  2547. assert_no_difference 'Attachment.count' do
  2548. put :update, :id => 1,
  2549. :issue => { :subject => '' },
  2550. :attachments => {'p0' => {'token' => attachment.token}}
  2551. assert_response :success
  2552. assert_template 'edit'
  2553. end
  2554. end
  2555. assert_select 'input[name=?][value=?]', 'attachments[p0][token]', attachment.token
  2556. assert_select 'input[name=?][value=?]', 'attachments[p0][filename]', 'testfile.txt'
  2557. end
  2558. def test_put_update_should_attach_saved_attachments
  2559. set_tmp_attachments_directory
  2560. attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
  2561. @request.session[:user_id] = 2
  2562. assert_difference 'Journal.count' do
  2563. assert_difference 'JournalDetail.count' do
  2564. assert_no_difference 'Attachment.count' do
  2565. put :update, :id => 1,
  2566. :issue => {:notes => 'Attachment added'},
  2567. :attachments => {'p0' => {'token' => attachment.token}}
  2568. assert_redirected_to '/issues/1'
  2569. end
  2570. end
  2571. end
  2572. attachment.reload
  2573. assert_equal Issue.find(1), attachment.container
  2574. journal = Journal.first(:order => 'id DESC')
  2575. assert_equal 1, journal.details.size
  2576. assert_equal 'testfile.txt', journal.details.first.value
  2577. end
  2578. def test_put_update_with_attachment_that_fails_to_save
  2579. set_tmp_attachments_directory
  2580. # Delete all fixtured journals, a race condition can occur causing the wrong
  2581. # journal to get fetched in the next find.
  2582. Journal.delete_all
  2583. # Mock out the unsaved attachment
  2584. Attachment.any_instance.stubs(:create).returns(Attachment.new)
  2585. # anonymous user
  2586. put :update,
  2587. :id => 1,
  2588. :issue => {:notes => ''},
  2589. :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
  2590. assert_redirected_to :action => 'show', :id => '1'
  2591. assert_equal '1 file(s) could not be saved.', flash[:warning]
  2592. end
  2593. def test_put_update_with_no_change
  2594. issue = Issue.find(1)
  2595. issue.journals.clear
  2596. ActionMailer::Base.deliveries.clear
  2597. put :update,
  2598. :id => 1,
  2599. :issue => {:notes => ''}
  2600. assert_redirected_to :action => 'show', :id => '1'
  2601. issue.reload
  2602. assert issue.journals.empty?
  2603. # No email should be sent
  2604. assert ActionMailer::Base.deliveries.empty?
  2605. end
  2606. def test_put_update_should_send_a_notification
  2607. @request.session[:user_id] = 2
  2608. ActionMailer::Base.deliveries.clear
  2609. issue = Issue.find(1)
  2610. old_subject = issue.subject
  2611. new_subject = 'Subject modified by IssuesControllerTest#test_post_edit'
  2612. put :update, :id => 1, :issue => {:subject => new_subject,
  2613. :priority_id => '6',
  2614. :category_id => '1' # no change
  2615. }
  2616. assert_equal 1, ActionMailer::Base.deliveries.size
  2617. end
  2618. def test_put_update_with_invalid_spent_time_hours_only
  2619. @request.session[:user_id] = 2
  2620. notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
  2621. assert_no_difference('Journal.count') do
  2622. put :update,
  2623. :id => 1,
  2624. :issue => {:notes => notes},
  2625. :time_entry => {"comments"=>"", "activity_id"=>"", "hours"=>"2z"}
  2626. end
  2627. assert_response :success
  2628. assert_template 'edit'
  2629. assert_error_tag :descendant => {:content => /Activity can&#x27;t be blank/}
  2630. assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
  2631. assert_select 'input[name=?][value=?]', 'time_entry[hours]', '2z'
  2632. end
  2633. def test_put_update_with_invalid_spent_time_comments_only
  2634. @request.session[:user_id] = 2
  2635. notes = 'Note added by IssuesControllerTest#test_post_edit_with_invalid_spent_time'
  2636. assert_no_difference('Journal.count') do
  2637. put :update,
  2638. :id => 1,
  2639. :issue => {:notes => notes},
  2640. :time_entry => {"comments"=>"this is my comment", "activity_id"=>"", "hours"=>""}
  2641. end
  2642. assert_response :success
  2643. assert_template 'edit'
  2644. assert_error_tag :descendant => {:content => /Activity can&#x27;t be blank/}
  2645. assert_error_tag :descendant => {:content => /Hours can&#x27;t be blank/}
  2646. assert_select 'textarea[name=?]', 'issue[notes]', :text => notes
  2647. assert_select 'input[name=?][value=?]', 'time_entry[comments]', 'this is my comment'
  2648. end
  2649. def test_put_update_should_allow_fixed_version_to_be_set_to_a_subproject
  2650. issue = Issue.find(2)
  2651. @request.session[:user_id] = 2
  2652. put :update,
  2653. :id => issue.id,
  2654. :issue => {
  2655. :fixed_version_id => 4
  2656. }
  2657. assert_response :redirect
  2658. issue.reload
  2659. assert_equal 4, issue.fixed_version_id
  2660. assert_not_equal issue.project_id, issue.fixed_version.project_id
  2661. end
  2662. def test_put_update_should_redirect_back_using_the_back_url_parameter
  2663. issue = Issue.find(2)
  2664. @request.session[:user_id] = 2
  2665. put :update,
  2666. :id => issue.id,
  2667. :issue => {
  2668. :fixed_version_id => 4
  2669. },
  2670. :back_url => '/issues'
  2671. assert_response :redirect
  2672. assert_redirected_to '/issues'
  2673. end
  2674. def test_put_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
  2675. issue = Issue.find(2)
  2676. @request.session[:user_id] = 2
  2677. put :update,
  2678. :id => issue.id,
  2679. :issue => {
  2680. :fixed_version_id => 4
  2681. },
  2682. :back_url => 'http://google.com'
  2683. assert_response :redirect
  2684. assert_redirected_to :controller => 'issues', :action => 'show', :id => issue.id
  2685. end
  2686. def test_get_bulk_edit
  2687. @request.session[:user_id] = 2
  2688. get :bulk_edit, :ids => [1, 2]
  2689. assert_response :success
  2690. assert_template 'bulk_edit'
  2691. assert_select 'ul#bulk-selection' do
  2692. assert_select 'li', 2
  2693. assert_select 'li a', :text => 'Bug #1'
  2694. end
  2695. assert_select 'form#bulk_edit_form[action=?]', '/issues/bulk_update' do
  2696. assert_select 'input[name=?]', 'ids[]', 2
  2697. assert_select 'input[name=?][value=1][type=hidden]', 'ids[]'
  2698. assert_select 'select[name=?]', 'issue[project_id]'
  2699. assert_select 'input[name=?]', 'issue[parent_issue_id]'
  2700. # Project specific custom field, date type
  2701. field = CustomField.find(9)
  2702. assert !field.is_for_all?
  2703. assert_equal 'date', field.field_format
  2704. assert_select 'input[name=?]', 'issue[custom_field_values][9]'
  2705. # System wide custom field
  2706. assert CustomField.find(1).is_for_all?
  2707. assert_select 'select[name=?]', 'issue[custom_field_values][1]'
  2708. # Be sure we don't display inactive IssuePriorities
  2709. assert ! IssuePriority.find(15).active?
  2710. assert_select 'select[name=?]', 'issue[priority_id]' do
  2711. assert_select 'option[value=15]', 0
  2712. end
  2713. end
  2714. end
  2715. def test_get_bulk_edit_on_different_projects
  2716. @request.session[:user_id] = 2
  2717. get :bulk_edit, :ids => [1, 2, 6]
  2718. assert_response :success
  2719. assert_template 'bulk_edit'
  2720. # Can not set issues from different projects as children of an issue
  2721. assert_select 'input[name=?]', 'issue[parent_issue_id]', 0
  2722. # Project specific custom field, date type
  2723. field = CustomField.find(9)
  2724. assert !field.is_for_all?
  2725. assert !field.project_ids.include?(Issue.find(6).project_id)
  2726. assert_select 'input[name=?]', 'issue[custom_field_values][9]', 0
  2727. end
  2728. def test_get_bulk_edit_with_user_custom_field
  2729. field = IssueCustomField.create!(:name => 'Tester', :field_format => 'user', :is_for_all => true)
  2730. @request.session[:user_id] = 2
  2731. get :bulk_edit, :ids => [1, 2]
  2732. assert_response :success
  2733. assert_template 'bulk_edit'
  2734. assert_select 'select.user_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
  2735. assert_select 'option', Project.find(1).users.count + 2 # "no change" + "none" options
  2736. end
  2737. end
  2738. def test_get_bulk_edit_with_version_custom_field
  2739. field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true)
  2740. @request.session[:user_id] = 2
  2741. get :bulk_edit, :ids => [1, 2]
  2742. assert_response :success
  2743. assert_template 'bulk_edit'
  2744. assert_select 'select.version_cf[name=?]', "issue[custom_field_values][#{field.id}]" do
  2745. assert_select 'option', Project.find(1).shared_versions.count + 2 # "no change" + "none" options
  2746. end
  2747. end
  2748. def test_get_bulk_edit_with_multi_custom_field
  2749. field = CustomField.find(1)
  2750. field.update_attribute :multiple, true
  2751. @request.session[:user_id] = 2
  2752. get :bulk_edit, :ids => [1, 2]
  2753. assert_response :success
  2754. assert_template 'bulk_edit'
  2755. assert_select 'select[name=?]', 'issue[custom_field_values][1][]' do
  2756. assert_select 'option', field.possible_values.size + 1 # "none" options
  2757. end
  2758. end
  2759. def test_bulk_edit_should_only_propose_statuses_allowed_for_all_issues
  2760. WorkflowTransition.delete_all
  2761. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 1)
  2762. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3)
  2763. WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4)
  2764. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 1)
  2765. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 3)
  2766. WorkflowTransition.create!(:role_id => 1, :tracker_id => 2, :old_status_id => 2, :new_status_id => 5)
  2767. @request.session[:user_id] = 2
  2768. get :bulk_edit, :ids => [1, 2]
  2769. assert_response :success
  2770. statuses = assigns(:available_statuses)
  2771. assert_not_nil statuses
  2772. assert_equal [1, 3], statuses.map(&:id).sort
  2773. assert_select 'select[name=?]', 'issue[status_id]' do
  2774. assert_select 'option', 3 # 2 statuses + "no change" option
  2775. end
  2776. end
  2777. def test_bulk_edit_should_propose_target_project_open_shared_versions
  2778. @request.session[:user_id] = 2
  2779. post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
  2780. assert_response :success
  2781. assert_template 'bulk_edit'
  2782. assert_equal Project.find(1).shared_versions.open.all.sort, assigns(:versions).sort
  2783. assert_select 'select[name=?]', 'issue[fixed_version_id]' do
  2784. assert_select 'option', :text => '2.0'
  2785. end
  2786. end
  2787. def test_bulk_edit_should_propose_target_project_categories
  2788. @request.session[:user_id] = 2
  2789. post :bulk_edit, :ids => [1, 2, 6], :issue => {:project_id => 1}
  2790. assert_response :success
  2791. assert_template 'bulk_edit'
  2792. assert_equal Project.find(1).issue_categories.sort, assigns(:categories).sort
  2793. assert_select 'select[name=?]', 'issue[category_id]' do
  2794. assert_select 'option', :text => 'Recipes'
  2795. end
  2796. end
  2797. def test_bulk_update
  2798. @request.session[:user_id] = 2
  2799. # update issues priority
  2800. post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
  2801. :issue => {:priority_id => 7,
  2802. :assigned_to_id => '',
  2803. :custom_field_values => {'2' => ''}}
  2804. assert_response 302
  2805. # check that the issues were updated
  2806. assert_equal [7, 7], Issue.find_all_by_id([1, 2]).collect {|i| i.priority.id}
  2807. issue = Issue.find(1)
  2808. journal = issue.journals.reorder('created_on DESC').first
  2809. assert_equal '125', issue.custom_value_for(2).value
  2810. assert_equal 'Bulk editing', journal.notes
  2811. assert_equal 1, journal.details.size
  2812. end
  2813. def test_bulk_update_with_group_assignee
  2814. group = Group.find(11)
  2815. project = Project.find(1)
  2816. project.members << Member.new(:principal => group, :roles => [Role.givable.first])
  2817. @request.session[:user_id] = 2
  2818. # update issues assignee
  2819. post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing',
  2820. :issue => {:priority_id => '',
  2821. :assigned_to_id => group.id,
  2822. :custom_field_values => {'2' => ''}}
  2823. assert_response 302
  2824. assert_equal [group, group], Issue.find_all_by_id([1, 2]).collect {|i| i.assigned_to}
  2825. end
  2826. def test_bulk_update_on_different_projects
  2827. @request.session[:user_id] = 2
  2828. # update issues priority
  2829. post :bulk_update, :ids => [1, 2, 6], :notes => 'Bulk editing',
  2830. :issue => {:priority_id => 7,
  2831. :assigned_to_id => '',
  2832. :custom_field_values => {'2' => ''}}
  2833. assert_response 302
  2834. # check that the issues were updated
  2835. assert_equal [7, 7, 7], Issue.find([1,2,6]).map(&:priority_id)
  2836. issue = Issue.find(1)
  2837. journal = issue.journals.reorder('created_on DESC').first
  2838. assert_equal '125', issue.custom_value_for(2).value
  2839. assert_equal 'Bulk editing', journal.notes
  2840. assert_equal 1, journal.details.size
  2841. end
  2842. def test_bulk_update_on_different_projects_without_rights
  2843. @request.session[:user_id] = 3
  2844. user = User.find(3)
  2845. action = { :controller => "issues", :action => "bulk_update" }
  2846. assert user.allowed_to?(action, Issue.find(1).project)
  2847. assert ! user.allowed_to?(action, Issue.find(6).project)
  2848. post :bulk_update, :ids => [1, 6], :notes => 'Bulk should fail',
  2849. :issue => {:priority_id => 7,
  2850. :assigned_to_id => '',
  2851. :custom_field_values => {'2' => ''}}
  2852. assert_response 403
  2853. assert_not_equal "Bulk should fail", Journal.last.notes
  2854. end
  2855. def test_bullk_update_should_send_a_notification
  2856. @request.session[:user_id] = 2
  2857. ActionMailer::Base.deliveries.clear
  2858. post(:bulk_update,
  2859. {
  2860. :ids => [1, 2],
  2861. :notes => 'Bulk editing',
  2862. :issue => {
  2863. :priority_id => 7,
  2864. :assigned_to_id => '',
  2865. :custom_field_values => {'2' => ''}
  2866. }
  2867. })
  2868. assert_response 302
  2869. assert_equal 2, ActionMailer::Base.deliveries.size
  2870. end
  2871. def test_bulk_update_project
  2872. @request.session[:user_id] = 2
  2873. post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}
  2874. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  2875. # Issues moved to project 2
  2876. assert_equal 2, Issue.find(1).project_id
  2877. assert_equal 2, Issue.find(2).project_id
  2878. # No tracker change
  2879. assert_equal 1, Issue.find(1).tracker_id
  2880. assert_equal 2, Issue.find(2).tracker_id
  2881. end
  2882. def test_bulk_update_project_on_single_issue_should_follow_when_needed
  2883. @request.session[:user_id] = 2
  2884. post :bulk_update, :id => 1, :issue => {:project_id => '2'}, :follow => '1'
  2885. assert_redirected_to '/issues/1'
  2886. end
  2887. def test_bulk_update_project_on_multiple_issues_should_follow_when_needed
  2888. @request.session[:user_id] = 2
  2889. post :bulk_update, :id => [1, 2], :issue => {:project_id => '2'}, :follow => '1'
  2890. assert_redirected_to '/projects/onlinestore/issues'
  2891. end
  2892. def test_bulk_update_tracker
  2893. @request.session[:user_id] = 2
  2894. post :bulk_update, :ids => [1, 2], :issue => {:tracker_id => '2'}
  2895. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  2896. assert_equal 2, Issue.find(1).tracker_id
  2897. assert_equal 2, Issue.find(2).tracker_id
  2898. end
  2899. def test_bulk_update_status
  2900. @request.session[:user_id] = 2
  2901. # update issues priority
  2902. post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing status',
  2903. :issue => {:priority_id => '',
  2904. :assigned_to_id => '',
  2905. :status_id => '5'}
  2906. assert_response 302
  2907. issue = Issue.find(1)
  2908. assert issue.closed?
  2909. end
  2910. def test_bulk_update_priority
  2911. @request.session[:user_id] = 2
  2912. post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
  2913. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  2914. assert_equal 6, Issue.find(1).priority_id
  2915. assert_equal 6, Issue.find(2).priority_id
  2916. end
  2917. def test_bulk_update_with_notes
  2918. @request.session[:user_id] = 2
  2919. post :bulk_update, :ids => [1, 2], :notes => 'Moving two issues'
  2920. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  2921. assert_equal 'Moving two issues', Issue.find(1).journals.sort_by(&:id).last.notes
  2922. assert_equal 'Moving two issues', Issue.find(2).journals.sort_by(&:id).last.notes
  2923. end
  2924. def test_bulk_update_parent_id
  2925. IssueRelation.delete_all
  2926. @request.session[:user_id] = 2
  2927. post :bulk_update, :ids => [1, 3],
  2928. :notes => 'Bulk editing parent',
  2929. :issue => {:priority_id => '', :assigned_to_id => '', :status_id => '', :parent_issue_id => '2'}
  2930. assert_response 302
  2931. parent = Issue.find(2)
  2932. assert_equal parent.id, Issue.find(1).parent_id
  2933. assert_equal parent.id, Issue.find(3).parent_id
  2934. assert_equal [1, 3], parent.children.collect(&:id).sort
  2935. end
  2936. def test_bulk_update_custom_field
  2937. @request.session[:user_id] = 2
  2938. # update issues priority
  2939. post :bulk_update, :ids => [1, 2], :notes => 'Bulk editing custom field',
  2940. :issue => {:priority_id => '',
  2941. :assigned_to_id => '',
  2942. :custom_field_values => {'2' => '777'}}
  2943. assert_response 302
  2944. issue = Issue.find(1)
  2945. journal = issue.journals.reorder('created_on DESC').first
  2946. assert_equal '777', issue.custom_value_for(2).value
  2947. assert_equal 1, journal.details.size
  2948. assert_equal '125', journal.details.first.old_value
  2949. assert_equal '777', journal.details.first.value
  2950. end
  2951. def test_bulk_update_custom_field_to_blank
  2952. @request.session[:user_id] = 2
  2953. post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing custom field',
  2954. :issue => {:priority_id => '',
  2955. :assigned_to_id => '',
  2956. :custom_field_values => {'1' => '__none__'}}
  2957. assert_response 302
  2958. assert_equal '', Issue.find(1).custom_field_value(1)
  2959. assert_equal '', Issue.find(3).custom_field_value(1)
  2960. end
  2961. def test_bulk_update_multi_custom_field
  2962. field = CustomField.find(1)
  2963. field.update_attribute :multiple, true
  2964. @request.session[:user_id] = 2
  2965. post :bulk_update, :ids => [1, 2, 3], :notes => 'Bulk editing multi custom field',
  2966. :issue => {:priority_id => '',
  2967. :assigned_to_id => '',
  2968. :custom_field_values => {'1' => ['MySQL', 'Oracle']}}
  2969. assert_response 302
  2970. assert_equal ['MySQL', 'Oracle'], Issue.find(1).custom_field_value(1).sort
  2971. assert_equal ['MySQL', 'Oracle'], Issue.find(3).custom_field_value(1).sort
  2972. # the custom field is not associated with the issue tracker
  2973. assert_nil Issue.find(2).custom_field_value(1)
  2974. end
  2975. def test_bulk_update_multi_custom_field_to_blank
  2976. field = CustomField.find(1)
  2977. field.update_attribute :multiple, true
  2978. @request.session[:user_id] = 2
  2979. post :bulk_update, :ids => [1, 3], :notes => 'Bulk editing multi custom field',
  2980. :issue => {:priority_id => '',
  2981. :assigned_to_id => '',
  2982. :custom_field_values => {'1' => ['__none__']}}
  2983. assert_response 302
  2984. assert_equal [''], Issue.find(1).custom_field_value(1)
  2985. assert_equal [''], Issue.find(3).custom_field_value(1)
  2986. end
  2987. def test_bulk_update_unassign
  2988. assert_not_nil Issue.find(2).assigned_to
  2989. @request.session[:user_id] = 2
  2990. # unassign issues
  2991. post :bulk_update, :ids => [1, 2], :notes => 'Bulk unassigning', :issue => {:assigned_to_id => 'none'}
  2992. assert_response 302
  2993. # check that the issues were updated
  2994. assert_nil Issue.find(2).assigned_to
  2995. end
  2996. def test_post_bulk_update_should_allow_fixed_version_to_be_set_to_a_subproject
  2997. @request.session[:user_id] = 2
  2998. post :bulk_update, :ids => [1,2], :issue => {:fixed_version_id => 4}
  2999. assert_response :redirect
  3000. issues = Issue.find([1,2])
  3001. issues.each do |issue|
  3002. assert_equal 4, issue.fixed_version_id
  3003. assert_not_equal issue.project_id, issue.fixed_version.project_id
  3004. end
  3005. end
  3006. def test_post_bulk_update_should_redirect_back_using_the_back_url_parameter
  3007. @request.session[:user_id] = 2
  3008. post :bulk_update, :ids => [1,2], :back_url => '/issues'
  3009. assert_response :redirect
  3010. assert_redirected_to '/issues'
  3011. end
  3012. def test_post_bulk_update_should_not_redirect_back_using_the_back_url_parameter_off_the_host
  3013. @request.session[:user_id] = 2
  3014. post :bulk_update, :ids => [1,2], :back_url => 'http://google.com'
  3015. assert_response :redirect
  3016. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => Project.find(1).identifier
  3017. end
  3018. def test_bulk_update_with_failure_should_set_flash
  3019. @request.session[:user_id] = 2
  3020. Issue.update_all("subject = ''", "id = 2") # Make it invalid
  3021. post :bulk_update, :ids => [1, 2], :issue => {:priority_id => 6}
  3022. assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook'
  3023. assert_equal 'Failed to save 1 issue(s) on 2 selected: #2.', flash[:error]
  3024. end
  3025. def test_get_bulk_copy
  3026. @request.session[:user_id] = 2
  3027. get :bulk_edit, :ids => [1, 2, 3], :copy => '1'
  3028. assert_response :success
  3029. assert_template 'bulk_edit'
  3030. issues = assigns(:issues)
  3031. assert_not_nil issues
  3032. assert_equal [1, 2, 3], issues.map(&:id).sort
  3033. assert_select 'input[name=copy_attachments]'
  3034. end
  3035. def test_bulk_copy_to_another_project
  3036. @request.session[:user_id] = 2
  3037. assert_difference 'Issue.count', 2 do
  3038. assert_no_difference 'Project.find(1).issues.count' do
  3039. post :bulk_update, :ids => [1, 2], :issue => {:project_id => '2'}, :copy => '1'
  3040. end
  3041. end
  3042. assert_redirected_to '/projects/ecookbook/issues'
  3043. copies = Issue.all(:order => 'id DESC', :limit => issues.size)
  3044. copies.each do |copy|
  3045. assert_equal 2, copy.project_id
  3046. end
  3047. end
  3048. def test_bulk_copy_should_allow_not_changing_the_issue_attributes
  3049. @request.session[:user_id] = 2
  3050. issues = [
  3051. Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1, :priority_id => 2, :subject => 'issue 1', :author_id => 1, :assigned_to_id => nil),
  3052. Issue.create!(:project_id => 2, :tracker_id => 3, :status_id => 2, :priority_id => 1, :subject => 'issue 2', :author_id => 2, :assigned_to_id => 3)
  3053. ]
  3054. assert_difference 'Issue.count', issues.size do
  3055. post :bulk_update, :ids => issues.map(&:id), :copy => '1',
  3056. :issue => {
  3057. :project_id => '', :tracker_id => '', :assigned_to_id => '',
  3058. :status_id => '', :start_date => '', :due_date => ''
  3059. }
  3060. end
  3061. copies = Issue.all(:order => 'id DESC', :limit => issues.size)
  3062. issues.each do |orig|
  3063. copy = copies.detect {|c| c.subject == orig.subject}
  3064. assert_not_nil copy
  3065. assert_equal orig.project_id, copy.project_id
  3066. assert_equal orig.tracker_id, copy.tracker_id
  3067. assert_equal orig.status_id, copy.status_id
  3068. assert_equal orig.assigned_to_id, copy.assigned_to_id
  3069. assert_equal orig.priority_id, copy.priority_id
  3070. end
  3071. end
  3072. def test_bulk_copy_should_allow_changing_the_issue_attributes
  3073. # Fixes random test failure with Mysql
  3074. # where Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
  3075. # doesn't return the expected results
  3076. Issue.delete_all("project_id=2")
  3077. @request.session[:user_id] = 2
  3078. assert_difference 'Issue.count', 2 do
  3079. assert_no_difference 'Project.find(1).issues.count' do
  3080. post :bulk_update, :ids => [1, 2], :copy => '1',
  3081. :issue => {
  3082. :project_id => '2', :tracker_id => '', :assigned_to_id => '4',
  3083. :status_id => '1', :start_date => '2009-12-01', :due_date => '2009-12-31'
  3084. }
  3085. end
  3086. end
  3087. copied_issues = Issue.all(:limit => 2, :order => 'id desc', :conditions => {:project_id => 2})
  3088. assert_equal 2, copied_issues.size
  3089. copied_issues.each do |issue|
  3090. assert_equal 2, issue.project_id, "Project is incorrect"
  3091. assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"
  3092. assert_equal 1, issue.status_id, "Status is incorrect"
  3093. assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"
  3094. assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"
  3095. end
  3096. end
  3097. def test_bulk_copy_should_allow_adding_a_note
  3098. @request.session[:user_id] = 2
  3099. assert_difference 'Issue.count', 1 do
  3100. post :bulk_update, :ids => [1], :copy => '1',
  3101. :notes => 'Copying one issue',
  3102. :issue => {
  3103. :project_id => '', :tracker_id => '', :assigned_to_id => '4',
  3104. :status_id => '3', :start_date => '2009-12-01', :due_date => '2009-12-31'
  3105. }
  3106. end
  3107. issue = Issue.first(:order => 'id DESC')
  3108. assert_equal 1, issue.journals.size
  3109. journal = issue.journals.first
  3110. assert_equal 0, journal.details.size
  3111. assert_equal 'Copying one issue', journal.notes
  3112. end
  3113. def test_bulk_copy_should_allow_not_copying_the_attachments
  3114. attachment_count = Issue.find(3).attachments.size
  3115. assert attachment_count > 0
  3116. @request.session[:user_id] = 2
  3117. assert_difference 'Issue.count', 1 do
  3118. assert_no_difference 'Attachment.count' do
  3119. post :bulk_update, :ids => [3], :copy => '1',
  3120. :issue => {
  3121. :project_id => ''
  3122. }
  3123. end
  3124. end
  3125. end
  3126. def test_bulk_copy_should_allow_copying_the_attachments
  3127. attachment_count = Issue.find(3).attachments.size
  3128. assert attachment_count > 0
  3129. @request.session[:user_id] = 2
  3130. assert_difference 'Issue.count', 1 do
  3131. assert_difference 'Attachment.count', attachment_count do
  3132. post :bulk_update, :ids => [3], :copy => '1', :copy_attachments => '1',
  3133. :issue => {
  3134. :project_id => ''
  3135. }
  3136. end
  3137. end
  3138. end
  3139. def test_bulk_copy_should_add_relations_with_copied_issues
  3140. @request.session[:user_id] = 2
  3141. assert_difference 'Issue.count', 2 do
  3142. assert_difference 'IssueRelation.count', 2 do
  3143. post :bulk_update, :ids => [1, 3], :copy => '1',
  3144. :issue => {
  3145. :project_id => '1'
  3146. }
  3147. end
  3148. end
  3149. end
  3150. def test_bulk_copy_should_allow_not_copying_the_subtasks
  3151. issue = Issue.generate_with_descendants!
  3152. @request.session[:user_id] = 2
  3153. assert_difference 'Issue.count', 1 do
  3154. post :bulk_update, :ids => [issue.id], :copy => '1',
  3155. :issue => {
  3156. :project_id => ''
  3157. }
  3158. end
  3159. end
  3160. def test_bulk_copy_should_allow_copying_the_subtasks
  3161. issue = Issue.generate_with_descendants!
  3162. count = issue.descendants.count
  3163. @request.session[:user_id] = 2
  3164. assert_difference 'Issue.count', count+1 do
  3165. post :bulk_update, :ids => [issue.id], :copy => '1', :copy_subtasks => '1',
  3166. :issue => {
  3167. :project_id => ''
  3168. }
  3169. end
  3170. copy = Issue.where(:parent_id => nil).order("id DESC").first
  3171. assert_equal count, copy.descendants.count
  3172. end
  3173. def test_bulk_copy_should_not_copy_selected_subtasks_twice
  3174. issue = Issue.generate_with_descendants!
  3175. count = issue.descendants.count
  3176. @request.session[:user_id] = 2
  3177. assert_difference 'Issue.count', count+1 do
  3178. post :bulk_update, :ids => issue.self_and_descendants.map(&:id), :copy => '1', :copy_subtasks => '1',
  3179. :issue => {
  3180. :project_id => ''
  3181. }
  3182. end
  3183. copy = Issue.where(:parent_id => nil).order("id DESC").first
  3184. assert_equal count, copy.descendants.count
  3185. end
  3186. def test_bulk_copy_to_another_project_should_follow_when_needed
  3187. @request.session[:user_id] = 2
  3188. post :bulk_update, :ids => [1], :copy => '1', :issue => {:project_id => 2}, :follow => '1'
  3189. issue = Issue.first(:order => 'id DESC')
  3190. assert_redirected_to :controller => 'issues', :action => 'show', :id => issue
  3191. end
  3192. def test_destroy_issue_with_no_time_entries
  3193. assert_nil TimeEntry.find_by_issue_id(2)
  3194. @request.session[:user_id] = 2
  3195. assert_difference 'Issue.count', -1 do
  3196. delete :destroy, :id => 2
  3197. end
  3198. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  3199. assert_nil Issue.find_by_id(2)
  3200. end
  3201. def test_destroy_issues_with_time_entries
  3202. @request.session[:user_id] = 2
  3203. assert_no_difference 'Issue.count' do
  3204. delete :destroy, :ids => [1, 3]
  3205. end
  3206. assert_response :success
  3207. assert_template 'destroy'
  3208. assert_not_nil assigns(:hours)
  3209. assert Issue.find_by_id(1) && Issue.find_by_id(3)
  3210. assert_select 'form' do
  3211. assert_select 'input[name=_method][value=delete]'
  3212. end
  3213. end
  3214. def test_destroy_issues_and_destroy_time_entries
  3215. @request.session[:user_id] = 2
  3216. assert_difference 'Issue.count', -2 do
  3217. assert_difference 'TimeEntry.count', -3 do
  3218. delete :destroy, :ids => [1, 3], :todo => 'destroy'
  3219. end
  3220. end
  3221. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  3222. assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
  3223. assert_nil TimeEntry.find_by_id([1, 2])
  3224. end
  3225. def test_destroy_issues_and_assign_time_entries_to_project
  3226. @request.session[:user_id] = 2
  3227. assert_difference 'Issue.count', -2 do
  3228. assert_no_difference 'TimeEntry.count' do
  3229. delete :destroy, :ids => [1, 3], :todo => 'nullify'
  3230. end
  3231. end
  3232. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  3233. assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
  3234. assert_nil TimeEntry.find(1).issue_id
  3235. assert_nil TimeEntry.find(2).issue_id
  3236. end
  3237. def test_destroy_issues_and_reassign_time_entries_to_another_issue
  3238. @request.session[:user_id] = 2
  3239. assert_difference 'Issue.count', -2 do
  3240. assert_no_difference 'TimeEntry.count' do
  3241. delete :destroy, :ids => [1, 3], :todo => 'reassign', :reassign_to_id => 2
  3242. end
  3243. end
  3244. assert_redirected_to :action => 'index', :project_id => 'ecookbook'
  3245. assert !(Issue.find_by_id(1) || Issue.find_by_id(3))
  3246. assert_equal 2, TimeEntry.find(1).issue_id
  3247. assert_equal 2, TimeEntry.find(2).issue_id
  3248. end
  3249. def test_destroy_issues_from_different_projects
  3250. @request.session[:user_id] = 2
  3251. assert_difference 'Issue.count', -3 do
  3252. delete :destroy, :ids => [1, 2, 6], :todo => 'destroy'
  3253. end
  3254. assert_redirected_to :controller => 'issues', :action => 'index'
  3255. assert !(Issue.find_by_id(1) || Issue.find_by_id(2) || Issue.find_by_id(6))
  3256. end
  3257. def test_destroy_parent_and_child_issues
  3258. parent = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Parent Issue')
  3259. child = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'Child Issue', :parent_issue_id => parent.id)
  3260. assert child.is_descendant_of?(parent.reload)
  3261. @request.session[:user_id] = 2
  3262. assert_difference 'Issue.count', -2 do
  3263. delete :destroy, :ids => [parent.id, child.id], :todo => 'destroy'
  3264. end
  3265. assert_response 302
  3266. end
  3267. def test_destroy_invalid_should_respond_with_404
  3268. @request.session[:user_id] = 2
  3269. assert_no_difference 'Issue.count' do
  3270. delete :destroy, :id => 999
  3271. end
  3272. assert_response 404
  3273. end
  3274. def test_default_search_scope
  3275. get :index
  3276. assert_select 'div#quick-search form' do
  3277. assert_select 'input[name=issues][value=1][type=hidden]'
  3278. end
  3279. end
  3280. end

软件技术创新是当今国家整体创新能力的重要基础和发展引擎。近年来,大众参与的软件创新与创业活动已经成为网络时代软件开发和应用的新形态,正在快速改变着全球软件创新模式和软件产业格局。 ...