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 163KB

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