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

issues_controller_test.rb 208KB

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