##// END OF EJS Templates
Fixes project editing route broken by r3313....
Jean-Philippe Lang -
r3200:dfe447f841f6
parent child
Show More
@@ -1,287 +1,287
1 1 ActionController::Routing::Routes.draw do |map|
2 2 # Add your own custom routes here.
3 3 # The priority is based upon order of creation: first created -> highest priority.
4 4
5 5 # Here's a sample route:
6 6 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
7 7 # Keep in mind you can assign values other than :controller and :action
8 8
9 9 map.home '', :controller => 'welcome'
10 10
11 11 map.signin 'login', :controller => 'account', :action => 'login'
12 12 map.signout 'logout', :controller => 'account', :action => 'logout'
13 13
14 14 map.connect 'roles/workflow/:id/:role_id/:tracker_id', :controller => 'roles', :action => 'workflow'
15 15 map.connect 'help/:ctrl/:page', :controller => 'help'
16 16
17 17 map.connect 'time_entries/:id/edit', :action => 'edit', :controller => 'timelog'
18 18 map.connect 'projects/:project_id/time_entries/new', :action => 'edit', :controller => 'timelog'
19 19 map.connect 'projects/:project_id/issues/:issue_id/time_entries/new', :action => 'edit', :controller => 'timelog'
20 20
21 21 map.with_options :controller => 'timelog' do |timelog|
22 22 timelog.connect 'projects/:project_id/time_entries', :action => 'details'
23 23
24 24 timelog.with_options :action => 'details', :conditions => {:method => :get} do |time_details|
25 25 time_details.connect 'time_entries'
26 26 time_details.connect 'time_entries.:format'
27 27 time_details.connect 'issues/:issue_id/time_entries'
28 28 time_details.connect 'issues/:issue_id/time_entries.:format'
29 29 time_details.connect 'projects/:project_id/time_entries.:format'
30 30 time_details.connect 'projects/:project_id/issues/:issue_id/time_entries'
31 31 time_details.connect 'projects/:project_id/issues/:issue_id/time_entries.:format'
32 32 end
33 33 timelog.connect 'projects/:project_id/time_entries/report', :action => 'report'
34 34 timelog.with_options :action => 'report',:conditions => {:method => :get} do |time_report|
35 35 time_report.connect 'time_entries/report'
36 36 time_report.connect 'time_entries/report.:format'
37 37 time_report.connect 'projects/:project_id/time_entries/report.:format'
38 38 end
39 39
40 40 timelog.with_options :action => 'edit', :conditions => {:method => :get} do |time_edit|
41 41 time_edit.connect 'issues/:issue_id/time_entries/new'
42 42 end
43 43
44 44 timelog.connect 'time_entries/:id/destroy', :action => 'destroy', :conditions => {:method => :post}
45 45 end
46 46
47 47 map.connect 'projects/:id/wiki', :controller => 'wikis', :action => 'edit', :conditions => {:method => :post}
48 48 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :get}
49 49 map.connect 'projects/:id/wiki/destroy', :controller => 'wikis', :action => 'destroy', :conditions => {:method => :post}
50 50 map.with_options :controller => 'wiki' do |wiki_routes|
51 51 wiki_routes.with_options :conditions => {:method => :get} do |wiki_views|
52 52 wiki_views.connect 'projects/:id/wiki/:page', :action => 'special', :page => /page_index|date_index|export/i
53 53 wiki_views.connect 'projects/:id/wiki/:page', :action => 'index', :page => nil
54 54 wiki_views.connect 'projects/:id/wiki/:page/edit', :action => 'edit'
55 55 wiki_views.connect 'projects/:id/wiki/:page/rename', :action => 'rename'
56 56 wiki_views.connect 'projects/:id/wiki/:page/history', :action => 'history'
57 57 wiki_views.connect 'projects/:id/wiki/:page/diff/:version/vs/:version_from', :action => 'diff'
58 58 wiki_views.connect 'projects/:id/wiki/:page/annotate/:version', :action => 'annotate'
59 59 end
60 60
61 61 wiki_routes.connect 'projects/:id/wiki/:page/:action',
62 62 :action => /edit|rename|destroy|preview|protect/,
63 63 :conditions => {:method => :post}
64 64 end
65 65
66 66 map.with_options :controller => 'messages' do |messages_routes|
67 67 messages_routes.with_options :conditions => {:method => :get} do |messages_views|
68 68 messages_views.connect 'boards/:board_id/topics/new', :action => 'new'
69 69 messages_views.connect 'boards/:board_id/topics/:id', :action => 'show'
70 70 messages_views.connect 'boards/:board_id/topics/:id/edit', :action => 'edit'
71 71 end
72 72 messages_routes.with_options :conditions => {:method => :post} do |messages_actions|
73 73 messages_actions.connect 'boards/:board_id/topics/new', :action => 'new'
74 74 messages_actions.connect 'boards/:board_id/topics/:id/replies', :action => 'reply'
75 75 messages_actions.connect 'boards/:board_id/topics/:id/:action', :action => /edit|destroy/
76 76 end
77 77 end
78 78
79 79 map.with_options :controller => 'boards' do |board_routes|
80 80 board_routes.with_options :conditions => {:method => :get} do |board_views|
81 81 board_views.connect 'projects/:project_id/boards', :action => 'index'
82 82 board_views.connect 'projects/:project_id/boards/new', :action => 'new'
83 83 board_views.connect 'projects/:project_id/boards/:id', :action => 'show'
84 84 board_views.connect 'projects/:project_id/boards/:id.:format', :action => 'show'
85 85 board_views.connect 'projects/:project_id/boards/:id/edit', :action => 'edit'
86 86 end
87 87 board_routes.with_options :conditions => {:method => :post} do |board_actions|
88 88 board_actions.connect 'projects/:project_id/boards', :action => 'new'
89 89 board_actions.connect 'projects/:project_id/boards/:id/:action', :action => /edit|destroy/
90 90 end
91 91 end
92 92
93 93 map.with_options :controller => 'documents' do |document_routes|
94 94 document_routes.with_options :conditions => {:method => :get} do |document_views|
95 95 document_views.connect 'projects/:project_id/documents', :action => 'index'
96 96 document_views.connect 'projects/:project_id/documents/new', :action => 'new'
97 97 document_views.connect 'documents/:id', :action => 'show'
98 98 document_views.connect 'documents/:id/edit', :action => 'edit'
99 99 end
100 100 document_routes.with_options :conditions => {:method => :post} do |document_actions|
101 101 document_actions.connect 'projects/:project_id/documents', :action => 'new'
102 102 document_actions.connect 'documents/:id/:action', :action => /destroy|edit/
103 103 end
104 104 end
105 105
106 106 map.with_options :controller => 'issues' do |issues_routes|
107 107 issues_routes.with_options :conditions => {:method => :get} do |issues_views|
108 108 issues_views.connect 'issues', :action => 'index'
109 109 issues_views.connect 'issues.:format', :action => 'index'
110 110 issues_views.connect 'projects/:project_id/issues', :action => 'index'
111 111 issues_views.connect 'projects/:project_id/issues.:format', :action => 'index'
112 112 issues_views.connect 'projects/:project_id/issues/new', :action => 'new'
113 113 issues_views.connect 'projects/:project_id/issues/gantt', :action => 'gantt'
114 114 issues_views.connect 'projects/:project_id/issues/calendar', :action => 'calendar'
115 115 issues_views.connect 'projects/:project_id/issues/:copy_from/copy', :action => 'new'
116 116 issues_views.connect 'issues/:id', :action => 'show', :id => /\d+/
117 117 issues_views.connect 'issues/:id.:format', :action => 'show', :id => /\d+/
118 118 issues_views.connect 'issues/:id/edit', :action => 'edit', :id => /\d+/
119 119 issues_views.connect 'issues/:id/move', :action => 'move', :id => /\d+/
120 120 end
121 121 issues_routes.with_options :conditions => {:method => :post} do |issues_actions|
122 122 issues_actions.connect 'issues', :action => 'index'
123 123 issues_actions.connect 'projects/:project_id/issues', :action => 'new'
124 124 issues_actions.connect 'issues/:id/quoted', :action => 'reply', :id => /\d+/
125 125 issues_actions.connect 'issues/:id/:action', :action => /edit|move|destroy/, :id => /\d+/
126 126 issues_actions.connect 'issues.:format', :action => 'new', :format => /xml/
127 127 end
128 128 issues_routes.with_options :conditions => {:method => :put} do |issues_actions|
129 129 issues_actions.connect 'issues/:id.:format', :action => 'edit', :id => /\d+/, :format => /xml/
130 130 end
131 131 issues_routes.with_options :conditions => {:method => :delete} do |issues_actions|
132 132 issues_actions.connect 'issues/:id.:format', :action => 'destroy', :id => /\d+/, :format => /xml/
133 133 end
134 134 issues_routes.connect 'issues/:action'
135 135 end
136 136
137 137 map.with_options :controller => 'issue_relations', :conditions => {:method => :post} do |relations|
138 138 relations.connect 'issues/:issue_id/relations/:id', :action => 'new'
139 139 relations.connect 'issues/:issue_id/relations/:id/destroy', :action => 'destroy'
140 140 end
141 141
142 142 map.with_options :controller => 'reports', :action => 'issue_report', :conditions => {:method => :get} do |reports|
143 143 reports.connect 'projects/:id/issues/report'
144 144 reports.connect 'projects/:id/issues/report/:detail'
145 145 end
146 146
147 147 map.with_options :controller => 'news' do |news_routes|
148 148 news_routes.with_options :conditions => {:method => :get} do |news_views|
149 149 news_views.connect 'news', :action => 'index'
150 150 news_views.connect 'projects/:project_id/news', :action => 'index'
151 151 news_views.connect 'projects/:project_id/news.:format', :action => 'index'
152 152 news_views.connect 'news.:format', :action => 'index'
153 153 news_views.connect 'projects/:project_id/news/new', :action => 'new'
154 154 news_views.connect 'news/:id', :action => 'show'
155 155 news_views.connect 'news/:id/edit', :action => 'edit'
156 156 end
157 157 news_routes.with_options do |news_actions|
158 158 news_actions.connect 'projects/:project_id/news', :action => 'new'
159 159 news_actions.connect 'news/:id/edit', :action => 'edit'
160 160 news_actions.connect 'news/:id/destroy', :action => 'destroy'
161 161 end
162 162 end
163 163
164 164 map.connect 'projects/:id/members/new', :controller => 'members', :action => 'new'
165 165
166 166 map.with_options :controller => 'users' do |users|
167 167 users.with_options :conditions => {:method => :get} do |user_views|
168 168 user_views.connect 'users', :action => 'index'
169 169 user_views.connect 'users/:id', :action => 'show', :id => /\d+/
170 170 user_views.connect 'users/new', :action => 'add'
171 171 user_views.connect 'users/:id/edit/:tab', :action => 'edit', :tab => nil
172 172 end
173 173 users.with_options :conditions => {:method => :post} do |user_actions|
174 174 user_actions.connect 'users', :action => 'add'
175 175 user_actions.connect 'users/new', :action => 'add'
176 176 user_actions.connect 'users/:id/edit', :action => 'edit'
177 177 user_actions.connect 'users/:id/memberships', :action => 'edit_membership'
178 178 user_actions.connect 'users/:id/memberships/:membership_id', :action => 'edit_membership'
179 179 user_actions.connect 'users/:id/memberships/:membership_id/destroy', :action => 'destroy_membership'
180 180 end
181 181 end
182 182
183 183 map.with_options :controller => 'projects' do |projects|
184 184 projects.with_options :conditions => {:method => :get} do |project_views|
185 185 project_views.connect 'projects', :action => 'index'
186 186 project_views.connect 'projects.:format', :action => 'index'
187 187 project_views.connect 'projects/new', :action => 'add'
188 188 project_views.connect 'projects/:id', :action => 'show'
189 189 project_views.connect 'projects/:id.:format', :action => 'show'
190 190 project_views.connect 'projects/:id/:action', :action => /roadmap|destroy|settings/
191 191 project_views.connect 'projects/:id/files', :action => 'list_files'
192 192 project_views.connect 'projects/:id/files/new', :action => 'add_file'
193 193 project_views.connect 'projects/:id/versions/new', :action => 'add_version'
194 194 project_views.connect 'projects/:id/categories/new', :action => 'add_issue_category'
195 195 project_views.connect 'projects/:id/settings/:tab', :action => 'settings'
196 196 end
197 197
198 198 projects.with_options :action => 'activity', :conditions => {:method => :get} do |activity|
199 199 activity.connect 'projects/:id/activity'
200 200 activity.connect 'projects/:id/activity.:format'
201 201 activity.connect 'activity', :id => nil
202 202 activity.connect 'activity.:format', :id => nil
203 203 end
204 204
205 205 projects.with_options :conditions => {:method => :post} do |project_actions|
206 206 project_actions.connect 'projects/new', :action => 'add'
207 207 project_actions.connect 'projects', :action => 'add'
208 208 project_actions.connect 'projects.:format', :action => 'add', :format => /xml/
209 project_actions.connect 'projects/:id/:action', :action => /destroy|archive|unarchive/
209 project_actions.connect 'projects/:id/:action', :action => /edit|destroy|archive|unarchive/
210 210 project_actions.connect 'projects/:id/files/new', :action => 'add_file'
211 211 project_actions.connect 'projects/:id/versions/new', :action => 'add_version'
212 212 project_actions.connect 'projects/:id/categories/new', :action => 'add_issue_category'
213 213 project_actions.connect 'projects/:id/activities/save', :action => 'save_activities'
214 214 end
215 215
216 216 projects.with_options :conditions => {:method => :put} do |project_actions|
217 217 project_actions.conditions 'projects/:id.:format', :action => 'edit', :format => /xml/
218 218 end
219 219
220 220 projects.with_options :conditions => {:method => :delete} do |project_actions|
221 221 project_actions.conditions 'projects/:id.:format', :action => 'destroy', :format => /xml/
222 222 project_actions.conditions 'projects/:id/reset_activities', :action => 'reset_activities'
223 223 end
224 224 end
225 225
226 226 map.with_options :controller => 'versions' do |versions|
227 227 versions.with_options :conditions => {:method => :post} do |version_actions|
228 228 version_actions.connect 'projects/:project_id/versions/close_completed', :action => 'close_completed'
229 229 end
230 230 end
231 231
232 232 map.with_options :controller => 'repositories' do |repositories|
233 233 repositories.with_options :conditions => {:method => :get} do |repository_views|
234 234 repository_views.connect 'projects/:id/repository', :action => 'show'
235 235 repository_views.connect 'projects/:id/repository/edit', :action => 'edit'
236 236 repository_views.connect 'projects/:id/repository/statistics', :action => 'stats'
237 237 repository_views.connect 'projects/:id/repository/revisions', :action => 'revisions'
238 238 repository_views.connect 'projects/:id/repository/revisions.:format', :action => 'revisions'
239 239 repository_views.connect 'projects/:id/repository/revisions/:rev', :action => 'revision'
240 240 repository_views.connect 'projects/:id/repository/revisions/:rev/diff', :action => 'diff'
241 241 repository_views.connect 'projects/:id/repository/revisions/:rev/diff.:format', :action => 'diff'
242 242 repository_views.connect 'projects/:id/repository/revisions/:rev/raw/*path', :action => 'entry', :format => 'raw', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
243 243 repository_views.connect 'projects/:id/repository/revisions/:rev/:action/*path', :requirements => { :rev => /[a-z0-9\.\-_]+/ }
244 244 repository_views.connect 'projects/:id/repository/raw/*path', :action => 'entry', :format => 'raw'
245 245 # TODO: why the following route is required?
246 246 repository_views.connect 'projects/:id/repository/entry/*path', :action => 'entry'
247 247 repository_views.connect 'projects/:id/repository/:action/*path'
248 248 end
249 249
250 250 repositories.connect 'projects/:id/repository/:action', :conditions => {:method => :post}
251 251 end
252 252
253 253 map.connect 'attachments/:id', :controller => 'attachments', :action => 'show', :id => /\d+/
254 254 map.connect 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/
255 255 map.connect 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/
256 256
257 257 map.resources :groups
258 258
259 259 #left old routes at the bottom for backwards compat
260 260 map.connect 'projects/:project_id/issues/:action', :controller => 'issues'
261 261 map.connect 'projects/:project_id/documents/:action', :controller => 'documents'
262 262 map.connect 'projects/:project_id/boards/:action/:id', :controller => 'boards'
263 263 map.connect 'boards/:board_id/topics/:action/:id', :controller => 'messages'
264 264 map.connect 'wiki/:id/:page/:action', :page => nil, :controller => 'wiki'
265 265 map.connect 'issues/:issue_id/relations/:action/:id', :controller => 'issue_relations'
266 266 map.connect 'projects/:project_id/news/:action', :controller => 'news'
267 267 map.connect 'projects/:project_id/timelog/:action/:id', :controller => 'timelog', :project_id => /.+/
268 268 map.with_options :controller => 'repositories' do |omap|
269 269 omap.repositories_show 'repositories/browse/:id/*path', :action => 'browse'
270 270 omap.repositories_changes 'repositories/changes/:id/*path', :action => 'changes'
271 271 omap.repositories_diff 'repositories/diff/:id/*path', :action => 'diff'
272 272 omap.repositories_entry 'repositories/entry/:id/*path', :action => 'entry'
273 273 omap.repositories_entry 'repositories/annotate/:id/*path', :action => 'annotate'
274 274 omap.connect 'repositories/revision/:id/:rev', :action => 'revision'
275 275 end
276 276
277 277 map.with_options :controller => 'sys' do |sys|
278 278 sys.connect 'sys/projects.:format', :action => 'projects', :conditions => {:method => :get}
279 279 sys.connect 'sys/projects/:id/repository.:format', :action => 'create_project_repository', :conditions => {:method => :post}
280 280 end
281 281
282 282 # Install the default route as the lowest priority.
283 283 map.connect ':controller/:action/:id'
284 284 map.connect 'robots.txt', :controller => 'welcome', :action => 'robots'
285 285 # Used for OpenID
286 286 map.root :controller => 'account', :action => 'login'
287 287 end
@@ -1,892 +1,899
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19 require 'projects_controller'
20 20
21 21 # Re-raise errors caught by the controller.
22 22 class ProjectsController; def rescue_action(e) raise e end; end
23 23
24 24 class ProjectsControllerTest < ActionController::TestCase
25 25 fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
26 26 :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
27 27 :attachments, :custom_fields, :custom_values, :time_entries
28 28
29 29 def setup
30 30 @controller = ProjectsController.new
31 31 @request = ActionController::TestRequest.new
32 32 @response = ActionController::TestResponse.new
33 33 @request.session[:user_id] = nil
34 34 Setting.default_language = 'en'
35 35 end
36 36
37 37 def test_index_routing
38 38 assert_routing(
39 39 {:method => :get, :path => '/projects'},
40 40 :controller => 'projects', :action => 'index'
41 41 )
42 42 end
43 43
44 44 def test_index
45 45 get :index
46 46 assert_response :success
47 47 assert_template 'index'
48 48 assert_not_nil assigns(:projects)
49 49
50 50 assert_tag :ul, :child => {:tag => 'li',
51 51 :descendant => {:tag => 'a', :content => 'eCookbook'},
52 52 :child => { :tag => 'ul',
53 53 :descendant => { :tag => 'a',
54 54 :content => 'Child of private child'
55 55 }
56 56 }
57 57 }
58 58
59 59 assert_no_tag :a, :content => /Private child of eCookbook/
60 60 end
61 61
62 62 def test_index_atom_routing
63 63 assert_routing(
64 64 {:method => :get, :path => '/projects.atom'},
65 65 :controller => 'projects', :action => 'index', :format => 'atom'
66 66 )
67 67 end
68 68
69 69 def test_index_atom
70 70 get :index, :format => 'atom'
71 71 assert_response :success
72 72 assert_template 'common/feed.atom.rxml'
73 73 assert_select 'feed>title', :text => 'Redmine: Latest projects'
74 74 assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
75 75 end
76 76
77 77 def test_add_routing
78 78 assert_routing(
79 79 {:method => :get, :path => '/projects/new'},
80 80 :controller => 'projects', :action => 'add'
81 81 )
82 82 assert_recognizes(
83 83 {:controller => 'projects', :action => 'add'},
84 84 {:method => :post, :path => '/projects/new'}
85 85 )
86 86 assert_recognizes(
87 87 {:controller => 'projects', :action => 'add'},
88 88 {:method => :post, :path => '/projects'}
89 89 )
90 90 end
91 91
92 92 context "#add" do
93 93 context "by admin user" do
94 94 setup do
95 95 @request.session[:user_id] = 1
96 96 end
97 97
98 98 should "accept get" do
99 99 get :add
100 100 assert_response :success
101 101 assert_template 'add'
102 102 end
103 103
104 104 should "accept post" do
105 105 post :add, :project => { :name => "blog",
106 106 :description => "weblog",
107 107 :identifier => "blog",
108 108 :is_public => 1,
109 109 :custom_field_values => { '3' => 'Beta' }
110 110 }
111 111 assert_redirected_to '/projects/blog/settings'
112 112
113 113 project = Project.find_by_name('blog')
114 114 assert_kind_of Project, project
115 115 assert_equal 'weblog', project.description
116 116 assert_equal true, project.is_public?
117 117 assert_nil project.parent
118 118 end
119 119
120 120 should "accept post with parent" do
121 121 post :add, :project => { :name => "blog",
122 122 :description => "weblog",
123 123 :identifier => "blog",
124 124 :is_public => 1,
125 125 :custom_field_values => { '3' => 'Beta' },
126 126 :parent_id => 1
127 127 }
128 128 assert_redirected_to '/projects/blog/settings'
129 129
130 130 project = Project.find_by_name('blog')
131 131 assert_kind_of Project, project
132 132 assert_equal Project.find(1), project.parent
133 133 end
134 134 end
135 135
136 136 context "by non-admin user with add_project permission" do
137 137 setup do
138 138 Role.non_member.add_permission! :add_project
139 139 @request.session[:user_id] = 9
140 140 end
141 141
142 142 should "accept get" do
143 143 get :add
144 144 assert_response :success
145 145 assert_template 'add'
146 146 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
147 147 end
148 148
149 149 should "accept post" do
150 150 post :add, :project => { :name => "blog",
151 151 :description => "weblog",
152 152 :identifier => "blog",
153 153 :is_public => 1,
154 154 :custom_field_values => { '3' => 'Beta' }
155 155 }
156 156
157 157 assert_redirected_to '/projects/blog/settings'
158 158
159 159 project = Project.find_by_name('blog')
160 160 assert_kind_of Project, project
161 161 assert_equal 'weblog', project.description
162 162 assert_equal true, project.is_public?
163 163
164 164 # User should be added as a project member
165 165 assert User.find(9).member_of?(project)
166 166 assert_equal 1, project.members.size
167 167 end
168 168
169 169 should "fail with parent_id" do
170 170 assert_no_difference 'Project.count' do
171 171 post :add, :project => { :name => "blog",
172 172 :description => "weblog",
173 173 :identifier => "blog",
174 174 :is_public => 1,
175 175 :custom_field_values => { '3' => 'Beta' },
176 176 :parent_id => 1
177 177 }
178 178 end
179 179 assert_response :success
180 180 project = assigns(:project)
181 181 assert_kind_of Project, project
182 182 assert_not_nil project.errors.on(:parent_id)
183 183 end
184 184 end
185 185
186 186 context "by non-admin user with add_subprojects permission" do
187 187 setup do
188 188 Role.find(1).remove_permission! :add_project
189 189 Role.find(1).add_permission! :add_subprojects
190 190 @request.session[:user_id] = 2
191 191 end
192 192
193 193 should "accept get" do
194 194 get :add, :parent_id => 'ecookbook'
195 195 assert_response :success
196 196 assert_template 'add'
197 197 # parent project selected
198 198 assert_tag :select, :attributes => {:name => 'project[parent_id]'},
199 199 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
200 200 # no empty value
201 201 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
202 202 :child => {:tag => 'option', :attributes => {:value => ''}}
203 203 end
204 204
205 205 should "accept post with parent_id" do
206 206 post :add, :project => { :name => "blog",
207 207 :description => "weblog",
208 208 :identifier => "blog",
209 209 :is_public => 1,
210 210 :custom_field_values => { '3' => 'Beta' },
211 211 :parent_id => 1
212 212 }
213 213 assert_redirected_to '/projects/blog/settings'
214 214 project = Project.find_by_name('blog')
215 215 end
216 216
217 217 should "fail without parent_id" do
218 218 assert_no_difference 'Project.count' do
219 219 post :add, :project => { :name => "blog",
220 220 :description => "weblog",
221 221 :identifier => "blog",
222 222 :is_public => 1,
223 223 :custom_field_values => { '3' => 'Beta' }
224 224 }
225 225 end
226 226 assert_response :success
227 227 project = assigns(:project)
228 228 assert_kind_of Project, project
229 229 assert_not_nil project.errors.on(:parent_id)
230 230 end
231 231
232 232 should "fail with unauthorized parent_id" do
233 233 assert !User.find(2).member_of?(Project.find(6))
234 234 assert_no_difference 'Project.count' do
235 235 post :add, :project => { :name => "blog",
236 236 :description => "weblog",
237 237 :identifier => "blog",
238 238 :is_public => 1,
239 239 :custom_field_values => { '3' => 'Beta' },
240 240 :parent_id => 6
241 241 }
242 242 end
243 243 assert_response :success
244 244 project = assigns(:project)
245 245 assert_kind_of Project, project
246 246 assert_not_nil project.errors.on(:parent_id)
247 247 end
248 248 end
249 249 end
250 250
251 251 def test_show_routing
252 252 assert_routing(
253 253 {:method => :get, :path => '/projects/test'},
254 254 :controller => 'projects', :action => 'show', :id => 'test'
255 255 )
256 256 end
257 257
258 258 def test_show_by_id
259 259 get :show, :id => 1
260 260 assert_response :success
261 261 assert_template 'show'
262 262 assert_not_nil assigns(:project)
263 263 end
264 264
265 265 def test_show_by_identifier
266 266 get :show, :id => 'ecookbook'
267 267 assert_response :success
268 268 assert_template 'show'
269 269 assert_not_nil assigns(:project)
270 270 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
271 271 end
272 272
273 273 def test_show_should_not_fail_when_custom_values_are_nil
274 274 project = Project.find_by_identifier('ecookbook')
275 275 project.custom_values.first.update_attribute(:value, nil)
276 276 get :show, :id => 'ecookbook'
277 277 assert_response :success
278 278 assert_template 'show'
279 279 assert_not_nil assigns(:project)
280 280 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
281 281 end
282 282
283 283 def test_private_subprojects_hidden
284 284 get :show, :id => 'ecookbook'
285 285 assert_response :success
286 286 assert_template 'show'
287 287 assert_no_tag :tag => 'a', :content => /Private child/
288 288 end
289 289
290 290 def test_private_subprojects_visible
291 291 @request.session[:user_id] = 2 # manager who is a member of the private subproject
292 292 get :show, :id => 'ecookbook'
293 293 assert_response :success
294 294 assert_template 'show'
295 295 assert_tag :tag => 'a', :content => /Private child/
296 296 end
297 297
298 298 def test_settings_routing
299 299 assert_routing(
300 300 {:method => :get, :path => '/projects/4223/settings'},
301 301 :controller => 'projects', :action => 'settings', :id => '4223'
302 302 )
303 303 assert_routing(
304 304 {:method => :get, :path => '/projects/4223/settings/members'},
305 305 :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
306 306 )
307 307 end
308 308
309 309 def test_settings
310 310 @request.session[:user_id] = 2 # manager
311 311 get :settings, :id => 1
312 312 assert_response :success
313 313 assert_template 'settings'
314 314 end
315 315
316 def test_edit_routing
317 assert_routing(
318 {:method => :post, :path => '/projects/4223/edit'},
319 :controller => 'projects', :action => 'edit', :id => '4223'
320 )
321 end
322
316 323 def test_edit
317 324 @request.session[:user_id] = 2 # manager
318 325 post :edit, :id => 1, :project => {:name => 'Test changed name',
319 326 :issue_custom_field_ids => ['']}
320 327 assert_redirected_to 'projects/ecookbook/settings'
321 328 project = Project.find(1)
322 329 assert_equal 'Test changed name', project.name
323 330 end
324 331
325 332 def test_add_version_routing
326 333 assert_routing(
327 334 {:method => :get, :path => 'projects/64/versions/new'},
328 335 :controller => 'projects', :action => 'add_version', :id => '64'
329 336 )
330 337 assert_routing(
331 338 #TODO: use PUT
332 339 {:method => :post, :path => 'projects/64/versions/new'},
333 340 :controller => 'projects', :action => 'add_version', :id => '64'
334 341 )
335 342 end
336 343
337 344 def test_add_version
338 345 @request.session[:user_id] = 2 # manager
339 346 assert_difference 'Version.count' do
340 347 post :add_version, :id => '1', :version => {:name => 'test_add_version'}
341 348 end
342 349 assert_redirected_to '/projects/ecookbook/settings/versions'
343 350 version = Version.find_by_name('test_add_version')
344 351 assert_not_nil version
345 352 assert_equal 1, version.project_id
346 353 end
347 354
348 355 def test_add_version_from_issue_form
349 356 @request.session[:user_id] = 2 # manager
350 357 assert_difference 'Version.count' do
351 358 xhr :post, :add_version, :id => '1', :version => {:name => 'test_add_version_from_issue_form'}
352 359 end
353 360 assert_response :success
354 361 assert_select_rjs :replace, 'issue_fixed_version_id'
355 362 version = Version.find_by_name('test_add_version_from_issue_form')
356 363 assert_not_nil version
357 364 assert_equal 1, version.project_id
358 365 end
359 366
360 367 def test_add_issue_category_routing
361 368 assert_routing(
362 369 {:method => :get, :path => 'projects/test/categories/new'},
363 370 :controller => 'projects', :action => 'add_issue_category', :id => 'test'
364 371 )
365 372 assert_routing(
366 373 #TODO: use PUT and update form
367 374 {:method => :post, :path => 'projects/64/categories/new'},
368 375 :controller => 'projects', :action => 'add_issue_category', :id => '64'
369 376 )
370 377 end
371 378
372 379 def test_destroy_routing
373 380 assert_routing(
374 381 {:method => :get, :path => '/projects/567/destroy'},
375 382 :controller => 'projects', :action => 'destroy', :id => '567'
376 383 )
377 384 assert_routing(
378 385 #TODO: use DELETE and update form
379 386 {:method => :post, :path => 'projects/64/destroy'},
380 387 :controller => 'projects', :action => 'destroy', :id => '64'
381 388 )
382 389 end
383 390
384 391 def test_get_destroy
385 392 @request.session[:user_id] = 1 # admin
386 393 get :destroy, :id => 1
387 394 assert_response :success
388 395 assert_template 'destroy'
389 396 assert_not_nil Project.find_by_id(1)
390 397 end
391 398
392 399 def test_post_destroy
393 400 @request.session[:user_id] = 1 # admin
394 401 post :destroy, :id => 1, :confirm => 1
395 402 assert_redirected_to 'admin/projects'
396 403 assert_nil Project.find_by_id(1)
397 404 end
398 405
399 406 def test_add_file
400 407 set_tmp_attachments_directory
401 408 @request.session[:user_id] = 2
402 409 Setting.notified_events = ['file_added']
403 410 ActionMailer::Base.deliveries.clear
404 411
405 412 assert_difference 'Attachment.count' do
406 413 post :add_file, :id => 1, :version_id => '',
407 414 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
408 415 end
409 416 assert_redirected_to 'projects/ecookbook/files'
410 417 a = Attachment.find(:first, :order => 'created_on DESC')
411 418 assert_equal 'testfile.txt', a.filename
412 419 assert_equal Project.find(1), a.container
413 420
414 421 mail = ActionMailer::Base.deliveries.last
415 422 assert_kind_of TMail::Mail, mail
416 423 assert_equal "[eCookbook] New file", mail.subject
417 424 assert mail.body.include?('testfile.txt')
418 425 end
419 426
420 427 def test_add_file_routing
421 428 assert_routing(
422 429 {:method => :get, :path => '/projects/33/files/new'},
423 430 :controller => 'projects', :action => 'add_file', :id => '33'
424 431 )
425 432 assert_routing(
426 433 {:method => :post, :path => '/projects/33/files/new'},
427 434 :controller => 'projects', :action => 'add_file', :id => '33'
428 435 )
429 436 end
430 437
431 438 def test_add_version_file
432 439 set_tmp_attachments_directory
433 440 @request.session[:user_id] = 2
434 441 Setting.notified_events = ['file_added']
435 442
436 443 assert_difference 'Attachment.count' do
437 444 post :add_file, :id => 1, :version_id => '2',
438 445 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
439 446 end
440 447 assert_redirected_to 'projects/ecookbook/files'
441 448 a = Attachment.find(:first, :order => 'created_on DESC')
442 449 assert_equal 'testfile.txt', a.filename
443 450 assert_equal Version.find(2), a.container
444 451 end
445 452
446 453 def test_list_files
447 454 get :list_files, :id => 1
448 455 assert_response :success
449 456 assert_template 'list_files'
450 457 assert_not_nil assigns(:containers)
451 458
452 459 # file attached to the project
453 460 assert_tag :a, :content => 'project_file.zip',
454 461 :attributes => { :href => '/attachments/download/8/project_file.zip' }
455 462
456 463 # file attached to a project's version
457 464 assert_tag :a, :content => 'version_file.zip',
458 465 :attributes => { :href => '/attachments/download/9/version_file.zip' }
459 466 end
460 467
461 468 def test_list_files_routing
462 469 assert_routing(
463 470 {:method => :get, :path => '/projects/33/files'},
464 471 :controller => 'projects', :action => 'list_files', :id => '33'
465 472 )
466 473 end
467 474
468 475 def test_roadmap_routing
469 476 assert_routing(
470 477 {:method => :get, :path => 'projects/33/roadmap'},
471 478 :controller => 'projects', :action => 'roadmap', :id => '33'
472 479 )
473 480 end
474 481
475 482 def test_roadmap
476 483 get :roadmap, :id => 1
477 484 assert_response :success
478 485 assert_template 'roadmap'
479 486 assert_not_nil assigns(:versions)
480 487 # Version with no date set appears
481 488 assert assigns(:versions).include?(Version.find(3))
482 489 # Completed version doesn't appear
483 490 assert !assigns(:versions).include?(Version.find(1))
484 491 end
485 492
486 493 def test_roadmap_with_completed_versions
487 494 get :roadmap, :id => 1, :completed => 1
488 495 assert_response :success
489 496 assert_template 'roadmap'
490 497 assert_not_nil assigns(:versions)
491 498 # Version with no date set appears
492 499 assert assigns(:versions).include?(Version.find(3))
493 500 # Completed version appears
494 501 assert assigns(:versions).include?(Version.find(1))
495 502 end
496 503
497 504 def test_roadmap_showing_subprojects_versions
498 505 get :roadmap, :id => 1, :with_subprojects => 1
499 506 assert_response :success
500 507 assert_template 'roadmap'
501 508 assert_not_nil assigns(:versions)
502 509 # Version on subproject appears
503 510 assert assigns(:versions).include?(Version.find(4))
504 511 end
505 512
506 513 def test_project_activity_routing
507 514 assert_routing(
508 515 {:method => :get, :path => '/projects/1/activity'},
509 516 :controller => 'projects', :action => 'activity', :id => '1'
510 517 )
511 518 end
512 519
513 520 def test_project_activity_atom_routing
514 521 assert_routing(
515 522 {:method => :get, :path => '/projects/1/activity.atom'},
516 523 :controller => 'projects', :action => 'activity', :id => '1', :format => 'atom'
517 524 )
518 525 end
519 526
520 527 def test_project_activity
521 528 get :activity, :id => 1, :with_subprojects => 0
522 529 assert_response :success
523 530 assert_template 'activity'
524 531 assert_not_nil assigns(:events_by_day)
525 532
526 533 assert_tag :tag => "h3",
527 534 :content => /#{2.days.ago.to_date.day}/,
528 535 :sibling => { :tag => "dl",
529 536 :child => { :tag => "dt",
530 537 :attributes => { :class => /issue-edit/ },
531 538 :child => { :tag => "a",
532 539 :content => /(#{IssueStatus.find(2).name})/,
533 540 }
534 541 }
535 542 }
536 543 end
537 544
538 545 def test_previous_project_activity
539 546 get :activity, :id => 1, :from => 3.days.ago.to_date
540 547 assert_response :success
541 548 assert_template 'activity'
542 549 assert_not_nil assigns(:events_by_day)
543 550
544 551 assert_tag :tag => "h3",
545 552 :content => /#{3.day.ago.to_date.day}/,
546 553 :sibling => { :tag => "dl",
547 554 :child => { :tag => "dt",
548 555 :attributes => { :class => /issue/ },
549 556 :child => { :tag => "a",
550 557 :content => /#{Issue.find(1).subject}/,
551 558 }
552 559 }
553 560 }
554 561 end
555 562
556 563 def test_global_activity_routing
557 564 assert_routing({:method => :get, :path => '/activity'}, :controller => 'projects', :action => 'activity', :id => nil)
558 565 end
559 566
560 567 def test_global_activity
561 568 get :activity
562 569 assert_response :success
563 570 assert_template 'activity'
564 571 assert_not_nil assigns(:events_by_day)
565 572
566 573 assert_tag :tag => "h3",
567 574 :content => /#{5.day.ago.to_date.day}/,
568 575 :sibling => { :tag => "dl",
569 576 :child => { :tag => "dt",
570 577 :attributes => { :class => /issue/ },
571 578 :child => { :tag => "a",
572 579 :content => /#{Issue.find(5).subject}/,
573 580 }
574 581 }
575 582 }
576 583 end
577 584
578 585 def test_user_activity
579 586 get :activity, :user_id => 2
580 587 assert_response :success
581 588 assert_template 'activity'
582 589 assert_not_nil assigns(:events_by_day)
583 590
584 591 assert_tag :tag => "h3",
585 592 :content => /#{3.day.ago.to_date.day}/,
586 593 :sibling => { :tag => "dl",
587 594 :child => { :tag => "dt",
588 595 :attributes => { :class => /issue/ },
589 596 :child => { :tag => "a",
590 597 :content => /#{Issue.find(1).subject}/,
591 598 }
592 599 }
593 600 }
594 601 end
595 602
596 603 def test_global_activity_atom_routing
597 604 assert_routing({:method => :get, :path => '/activity.atom'}, :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom')
598 605 end
599 606
600 607 def test_activity_atom_feed
601 608 get :activity, :format => 'atom'
602 609 assert_response :success
603 610 assert_template 'common/feed.atom.rxml'
604 611 end
605 612
606 613 def test_archive_routing
607 614 assert_routing(
608 615 #TODO: use PUT to project path and modify form
609 616 {:method => :post, :path => 'projects/64/archive'},
610 617 :controller => 'projects', :action => 'archive', :id => '64'
611 618 )
612 619 end
613 620
614 621 def test_archive
615 622 @request.session[:user_id] = 1 # admin
616 623 post :archive, :id => 1
617 624 assert_redirected_to 'admin/projects'
618 625 assert !Project.find(1).active?
619 626 end
620 627
621 628 def test_unarchive_routing
622 629 assert_routing(
623 630 #TODO: use PUT to project path and modify form
624 631 {:method => :post, :path => '/projects/567/unarchive'},
625 632 :controller => 'projects', :action => 'unarchive', :id => '567'
626 633 )
627 634 end
628 635
629 636 def test_unarchive
630 637 @request.session[:user_id] = 1 # admin
631 638 Project.find(1).archive
632 639 post :unarchive, :id => 1
633 640 assert_redirected_to 'admin/projects'
634 641 assert Project.find(1).active?
635 642 end
636 643
637 644 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
638 645 CustomField.delete_all
639 646 parent = nil
640 647 6.times do |i|
641 648 p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
642 649 p.set_parent!(parent)
643 650 get :show, :id => p
644 651 assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
645 652 :children => { :count => [i, 3].min,
646 653 :only => { :tag => 'a' } }
647 654
648 655 parent = p
649 656 end
650 657 end
651 658
652 659 def test_copy_with_project
653 660 @request.session[:user_id] = 1 # admin
654 661 get :copy, :id => 1
655 662 assert_response :success
656 663 assert_template 'copy'
657 664 assert assigns(:project)
658 665 assert_equal Project.find(1).description, assigns(:project).description
659 666 assert_nil assigns(:project).id
660 667 end
661 668
662 669 def test_copy_without_project
663 670 @request.session[:user_id] = 1 # admin
664 671 get :copy
665 672 assert_response :redirect
666 673 assert_redirected_to :controller => 'admin', :action => 'projects'
667 674 end
668 675
669 676 def test_jump_should_redirect_to_active_tab
670 677 get :show, :id => 1, :jump => 'issues'
671 678 assert_redirected_to 'projects/ecookbook/issues'
672 679 end
673 680
674 681 def test_jump_should_not_redirect_to_inactive_tab
675 682 get :show, :id => 3, :jump => 'documents'
676 683 assert_response :success
677 684 assert_template 'show'
678 685 end
679 686
680 687 def test_jump_should_not_redirect_to_unknown_tab
681 688 get :show, :id => 3, :jump => 'foobar'
682 689 assert_response :success
683 690 assert_template 'show'
684 691 end
685 692
686 693 def test_reset_activities_routing
687 694 assert_routing({:method => :delete, :path => 'projects/64/reset_activities'},
688 695 :controller => 'projects', :action => 'reset_activities', :id => '64')
689 696 end
690 697
691 698 def test_reset_activities
692 699 @request.session[:user_id] = 2 # manager
693 700 project_activity = TimeEntryActivity.new({
694 701 :name => 'Project Specific',
695 702 :parent => TimeEntryActivity.find(:first),
696 703 :project => Project.find(1),
697 704 :active => true
698 705 })
699 706 assert project_activity.save
700 707 project_activity_two = TimeEntryActivity.new({
701 708 :name => 'Project Specific Two',
702 709 :parent => TimeEntryActivity.find(:last),
703 710 :project => Project.find(1),
704 711 :active => true
705 712 })
706 713 assert project_activity_two.save
707 714
708 715 delete :reset_activities, :id => 1
709 716 assert_response :redirect
710 717 assert_redirected_to 'projects/ecookbook/settings/activities'
711 718
712 719 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
713 720 assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
714 721 end
715 722
716 723 def test_reset_activities_should_reassign_time_entries_back_to_the_system_activity
717 724 @request.session[:user_id] = 2 # manager
718 725 project_activity = TimeEntryActivity.new({
719 726 :name => 'Project Specific Design',
720 727 :parent => TimeEntryActivity.find(9),
721 728 :project => Project.find(1),
722 729 :active => true
723 730 })
724 731 assert project_activity.save
725 732 assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
726 733 assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
727 734
728 735 delete :reset_activities, :id => 1
729 736 assert_response :redirect
730 737 assert_redirected_to 'projects/ecookbook/settings/activities'
731 738
732 739 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
733 740 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity"
734 741 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
735 742 end
736 743
737 744 def test_save_activities_routing
738 745 assert_routing({:method => :post, :path => 'projects/64/activities/save'},
739 746 :controller => 'projects', :action => 'save_activities', :id => '64')
740 747 end
741 748
742 749 def test_save_activities_to_override_system_activities
743 750 @request.session[:user_id] = 2 # manager
744 751 billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
745 752
746 753 post :save_activities, :id => 1, :enumerations => {
747 754 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate
748 755 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
749 756 "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
750 757 "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
751 758 }
752 759
753 760 assert_response :redirect
754 761 assert_redirected_to 'projects/ecookbook/settings/activities'
755 762
756 763 # Created project specific activities...
757 764 project = Project.find('ecookbook')
758 765
759 766 # ... Design
760 767 design = project.time_entry_activities.find_by_name("Design")
761 768 assert design, "Project activity not found"
762 769
763 770 assert_equal 9, design.parent_id # Relate to the system activity
764 771 assert_not_equal design.parent.id, design.id # Different records
765 772 assert_equal design.parent.name, design.name # Same name
766 773 assert !design.active?
767 774
768 775 # ... Development
769 776 development = project.time_entry_activities.find_by_name("Development")
770 777 assert development, "Project activity not found"
771 778
772 779 assert_equal 10, development.parent_id # Relate to the system activity
773 780 assert_not_equal development.parent.id, development.id # Different records
774 781 assert_equal development.parent.name, development.name # Same name
775 782 assert development.active?
776 783 assert_equal "0", development.custom_value_for(billable_field).value
777 784
778 785 # ... Inactive Activity
779 786 previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
780 787 assert previously_inactive, "Project activity not found"
781 788
782 789 assert_equal 14, previously_inactive.parent_id # Relate to the system activity
783 790 assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
784 791 assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
785 792 assert previously_inactive.active?
786 793 assert_equal "1", previously_inactive.custom_value_for(billable_field).value
787 794
788 795 # ... QA
789 796 assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
790 797 end
791 798
792 799 def test_save_activities_will_update_project_specific_activities
793 800 @request.session[:user_id] = 2 # manager
794 801
795 802 project_activity = TimeEntryActivity.new({
796 803 :name => 'Project Specific',
797 804 :parent => TimeEntryActivity.find(:first),
798 805 :project => Project.find(1),
799 806 :active => true
800 807 })
801 808 assert project_activity.save
802 809 project_activity_two = TimeEntryActivity.new({
803 810 :name => 'Project Specific Two',
804 811 :parent => TimeEntryActivity.find(:last),
805 812 :project => Project.find(1),
806 813 :active => true
807 814 })
808 815 assert project_activity_two.save
809 816
810 817
811 818 post :save_activities, :id => 1, :enumerations => {
812 819 project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate
813 820 project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
814 821 }
815 822
816 823 assert_response :redirect
817 824 assert_redirected_to 'projects/ecookbook/settings/activities'
818 825
819 826 # Created project specific activities...
820 827 project = Project.find('ecookbook')
821 828 assert_equal 2, project.time_entry_activities.count
822 829
823 830 activity_one = project.time_entry_activities.find_by_name(project_activity.name)
824 831 assert activity_one, "Project activity not found"
825 832 assert_equal project_activity.id, activity_one.id
826 833 assert !activity_one.active?
827 834
828 835 activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
829 836 assert activity_two, "Project activity not found"
830 837 assert_equal project_activity_two.id, activity_two.id
831 838 assert !activity_two.active?
832 839 end
833 840
834 841 def test_save_activities_when_creating_new_activities_will_convert_existing_data
835 842 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
836 843
837 844 @request.session[:user_id] = 2 # manager
838 845 post :save_activities, :id => 1, :enumerations => {
839 846 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate
840 847 }
841 848 assert_response :redirect
842 849
843 850 # No more TimeEntries using the system activity
844 851 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities"
845 852 # All TimeEntries using project activity
846 853 project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
847 854 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(project_specific_activity.id, 1).size, "No Time Entries assigned to the project activity"
848 855 end
849 856
850 857 def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
851 858 # TODO: Need to cause an exception on create but these tests
852 859 # aren't setup for mocking. Just create a record now so the
853 860 # second one is a dupicate
854 861 parent = TimeEntryActivity.find(9)
855 862 TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true})
856 863 TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
857 864
858 865 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
859 866 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
860 867
861 868 @request.session[:user_id] = 2 # manager
862 869 post :save_activities, :id => 1, :enumerations => {
863 870 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
864 871 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
865 872 }
866 873 assert_response :redirect
867 874
868 875 # TimeEntries shouldn't have been reassigned on the failed record
869 876 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
870 877 # TimeEntries shouldn't have been reassigned on the saved record either
871 878 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities"
872 879 end
873 880
874 881 # A hook that is manually registered later
875 882 class ProjectBasedTemplate < Redmine::Hook::ViewListener
876 883 def view_layouts_base_html_head(context)
877 884 # Adds a project stylesheet
878 885 stylesheet_link_tag(context[:project].identifier) if context[:project]
879 886 end
880 887 end
881 888 # Don't use this hook now
882 889 Redmine::Hook.clear_listeners
883 890
884 891 def test_hook_response
885 892 Redmine::Hook.add_listener(ProjectBasedTemplate)
886 893 get :show, :id => 1
887 894 assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
888 895 :parent => {:tag => 'head'}
889 896
890 897 Redmine::Hook.clear_listeners
891 898 end
892 899 end
General Comments 0
You need to be logged in to leave comments. Login now