##// END OF EJS Templates
Fixes URLs in atom feeds broken by r3681 (#5403)....
Jean-Philippe Lang -
r3589:51c8f3143c86
parent child
Show More
@@ -1,712 +1,715
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
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
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.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'projects_controller'
19 require 'projects_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class ProjectsController; def rescue_action(e) raise e end; end
22 class ProjectsController; def rescue_action(e) raise e end; end
23
23
24 class ProjectsControllerTest < ActionController::TestCase
24 class ProjectsControllerTest < ActionController::TestCase
25 fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
25 fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
26 :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
26 :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
27 :attachments, :custom_fields, :custom_values, :time_entries
27 :attachments, :custom_fields, :custom_values, :time_entries
28
28
29 def setup
29 def setup
30 @controller = ProjectsController.new
30 @controller = ProjectsController.new
31 @request = ActionController::TestRequest.new
31 @request = ActionController::TestRequest.new
32 @response = ActionController::TestResponse.new
32 @response = ActionController::TestResponse.new
33 @request.session[:user_id] = nil
33 @request.session[:user_id] = nil
34 Setting.default_language = 'en'
34 Setting.default_language = 'en'
35 end
35 end
36
36
37 def test_index
37 def test_index
38 get :index
38 get :index
39 assert_response :success
39 assert_response :success
40 assert_template 'index'
40 assert_template 'index'
41 assert_not_nil assigns(:projects)
41 assert_not_nil assigns(:projects)
42
42
43 assert_tag :ul, :child => {:tag => 'li',
43 assert_tag :ul, :child => {:tag => 'li',
44 :descendant => {:tag => 'a', :content => 'eCookbook'},
44 :descendant => {:tag => 'a', :content => 'eCookbook'},
45 :child => { :tag => 'ul',
45 :child => { :tag => 'ul',
46 :descendant => { :tag => 'a',
46 :descendant => { :tag => 'a',
47 :content => 'Child of private child'
47 :content => 'Child of private child'
48 }
48 }
49 }
49 }
50 }
50 }
51
51
52 assert_no_tag :a, :content => /Private child of eCookbook/
52 assert_no_tag :a, :content => /Private child of eCookbook/
53 end
53 end
54
54
55 def test_index_atom
55 def test_index_atom
56 get :index, :format => 'atom'
56 get :index, :format => 'atom'
57 assert_response :success
57 assert_response :success
58 assert_template 'common/feed.atom.rxml'
58 assert_template 'common/feed.atom.rxml'
59 assert_select 'feed>title', :text => 'Redmine: Latest projects'
59 assert_select 'feed>title', :text => 'Redmine: Latest projects'
60 assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
60 assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
61 end
61 end
62
62
63 context "#add" do
63 context "#add" do
64 context "by admin user" do
64 context "by admin user" do
65 setup do
65 setup do
66 @request.session[:user_id] = 1
66 @request.session[:user_id] = 1
67 end
67 end
68
68
69 should "accept get" do
69 should "accept get" do
70 get :add
70 get :add
71 assert_response :success
71 assert_response :success
72 assert_template 'add'
72 assert_template 'add'
73 end
73 end
74
74
75 should "accept post" do
75 should "accept post" do
76 post :add, :project => { :name => "blog",
76 post :add, :project => { :name => "blog",
77 :description => "weblog",
77 :description => "weblog",
78 :identifier => "blog",
78 :identifier => "blog",
79 :is_public => 1,
79 :is_public => 1,
80 :custom_field_values => { '3' => 'Beta' }
80 :custom_field_values => { '3' => 'Beta' }
81 }
81 }
82 assert_redirected_to '/projects/blog/settings'
82 assert_redirected_to '/projects/blog/settings'
83
83
84 project = Project.find_by_name('blog')
84 project = Project.find_by_name('blog')
85 assert_kind_of Project, project
85 assert_kind_of Project, project
86 assert_equal 'weblog', project.description
86 assert_equal 'weblog', project.description
87 assert_equal true, project.is_public?
87 assert_equal true, project.is_public?
88 assert_nil project.parent
88 assert_nil project.parent
89 end
89 end
90
90
91 should "accept post with parent" do
91 should "accept post with parent" do
92 post :add, :project => { :name => "blog",
92 post :add, :project => { :name => "blog",
93 :description => "weblog",
93 :description => "weblog",
94 :identifier => "blog",
94 :identifier => "blog",
95 :is_public => 1,
95 :is_public => 1,
96 :custom_field_values => { '3' => 'Beta' },
96 :custom_field_values => { '3' => 'Beta' },
97 :parent_id => 1
97 :parent_id => 1
98 }
98 }
99 assert_redirected_to '/projects/blog/settings'
99 assert_redirected_to '/projects/blog/settings'
100
100
101 project = Project.find_by_name('blog')
101 project = Project.find_by_name('blog')
102 assert_kind_of Project, project
102 assert_kind_of Project, project
103 assert_equal Project.find(1), project.parent
103 assert_equal Project.find(1), project.parent
104 end
104 end
105 end
105 end
106
106
107 context "by non-admin user with add_project permission" do
107 context "by non-admin user with add_project permission" do
108 setup do
108 setup do
109 Role.non_member.add_permission! :add_project
109 Role.non_member.add_permission! :add_project
110 @request.session[:user_id] = 9
110 @request.session[:user_id] = 9
111 end
111 end
112
112
113 should "accept get" do
113 should "accept get" do
114 get :add
114 get :add
115 assert_response :success
115 assert_response :success
116 assert_template 'add'
116 assert_template 'add'
117 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
117 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
118 end
118 end
119
119
120 should "accept post" do
120 should "accept post" do
121 post :add, :project => { :name => "blog",
121 post :add, :project => { :name => "blog",
122 :description => "weblog",
122 :description => "weblog",
123 :identifier => "blog",
123 :identifier => "blog",
124 :is_public => 1,
124 :is_public => 1,
125 :custom_field_values => { '3' => 'Beta' }
125 :custom_field_values => { '3' => 'Beta' }
126 }
126 }
127
127
128 assert_redirected_to '/projects/blog/settings'
128 assert_redirected_to '/projects/blog/settings'
129
129
130 project = Project.find_by_name('blog')
130 project = Project.find_by_name('blog')
131 assert_kind_of Project, project
131 assert_kind_of Project, project
132 assert_equal 'weblog', project.description
132 assert_equal 'weblog', project.description
133 assert_equal true, project.is_public?
133 assert_equal true, project.is_public?
134
134
135 # User should be added as a project member
135 # User should be added as a project member
136 assert User.find(9).member_of?(project)
136 assert User.find(9).member_of?(project)
137 assert_equal 1, project.members.size
137 assert_equal 1, project.members.size
138 end
138 end
139
139
140 should "fail with parent_id" do
140 should "fail with parent_id" do
141 assert_no_difference 'Project.count' do
141 assert_no_difference 'Project.count' do
142 post :add, :project => { :name => "blog",
142 post :add, :project => { :name => "blog",
143 :description => "weblog",
143 :description => "weblog",
144 :identifier => "blog",
144 :identifier => "blog",
145 :is_public => 1,
145 :is_public => 1,
146 :custom_field_values => { '3' => 'Beta' },
146 :custom_field_values => { '3' => 'Beta' },
147 :parent_id => 1
147 :parent_id => 1
148 }
148 }
149 end
149 end
150 assert_response :success
150 assert_response :success
151 project = assigns(:project)
151 project = assigns(:project)
152 assert_kind_of Project, project
152 assert_kind_of Project, project
153 assert_not_nil project.errors.on(:parent_id)
153 assert_not_nil project.errors.on(:parent_id)
154 end
154 end
155 end
155 end
156
156
157 context "by non-admin user with add_subprojects permission" do
157 context "by non-admin user with add_subprojects permission" do
158 setup do
158 setup do
159 Role.find(1).remove_permission! :add_project
159 Role.find(1).remove_permission! :add_project
160 Role.find(1).add_permission! :add_subprojects
160 Role.find(1).add_permission! :add_subprojects
161 @request.session[:user_id] = 2
161 @request.session[:user_id] = 2
162 end
162 end
163
163
164 should "accept get" do
164 should "accept get" do
165 get :add, :parent_id => 'ecookbook'
165 get :add, :parent_id => 'ecookbook'
166 assert_response :success
166 assert_response :success
167 assert_template 'add'
167 assert_template 'add'
168 # parent project selected
168 # parent project selected
169 assert_tag :select, :attributes => {:name => 'project[parent_id]'},
169 assert_tag :select, :attributes => {:name => 'project[parent_id]'},
170 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
170 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
171 # no empty value
171 # no empty value
172 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
172 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
173 :child => {:tag => 'option', :attributes => {:value => ''}}
173 :child => {:tag => 'option', :attributes => {:value => ''}}
174 end
174 end
175
175
176 should "accept post with parent_id" do
176 should "accept post with parent_id" do
177 post :add, :project => { :name => "blog",
177 post :add, :project => { :name => "blog",
178 :description => "weblog",
178 :description => "weblog",
179 :identifier => "blog",
179 :identifier => "blog",
180 :is_public => 1,
180 :is_public => 1,
181 :custom_field_values => { '3' => 'Beta' },
181 :custom_field_values => { '3' => 'Beta' },
182 :parent_id => 1
182 :parent_id => 1
183 }
183 }
184 assert_redirected_to '/projects/blog/settings'
184 assert_redirected_to '/projects/blog/settings'
185 project = Project.find_by_name('blog')
185 project = Project.find_by_name('blog')
186 end
186 end
187
187
188 should "fail without parent_id" do
188 should "fail without parent_id" do
189 assert_no_difference 'Project.count' do
189 assert_no_difference 'Project.count' do
190 post :add, :project => { :name => "blog",
190 post :add, :project => { :name => "blog",
191 :description => "weblog",
191 :description => "weblog",
192 :identifier => "blog",
192 :identifier => "blog",
193 :is_public => 1,
193 :is_public => 1,
194 :custom_field_values => { '3' => 'Beta' }
194 :custom_field_values => { '3' => 'Beta' }
195 }
195 }
196 end
196 end
197 assert_response :success
197 assert_response :success
198 project = assigns(:project)
198 project = assigns(:project)
199 assert_kind_of Project, project
199 assert_kind_of Project, project
200 assert_not_nil project.errors.on(:parent_id)
200 assert_not_nil project.errors.on(:parent_id)
201 end
201 end
202
202
203 should "fail with unauthorized parent_id" do
203 should "fail with unauthorized parent_id" do
204 assert !User.find(2).member_of?(Project.find(6))
204 assert !User.find(2).member_of?(Project.find(6))
205 assert_no_difference 'Project.count' do
205 assert_no_difference 'Project.count' do
206 post :add, :project => { :name => "blog",
206 post :add, :project => { :name => "blog",
207 :description => "weblog",
207 :description => "weblog",
208 :identifier => "blog",
208 :identifier => "blog",
209 :is_public => 1,
209 :is_public => 1,
210 :custom_field_values => { '3' => 'Beta' },
210 :custom_field_values => { '3' => 'Beta' },
211 :parent_id => 6
211 :parent_id => 6
212 }
212 }
213 end
213 end
214 assert_response :success
214 assert_response :success
215 project = assigns(:project)
215 project = assigns(:project)
216 assert_kind_of Project, project
216 assert_kind_of Project, project
217 assert_not_nil project.errors.on(:parent_id)
217 assert_not_nil project.errors.on(:parent_id)
218 end
218 end
219 end
219 end
220 end
220 end
221
221
222 def test_show_by_id
222 def test_show_by_id
223 get :show, :id => 1
223 get :show, :id => 1
224 assert_response :success
224 assert_response :success
225 assert_template 'show'
225 assert_template 'show'
226 assert_not_nil assigns(:project)
226 assert_not_nil assigns(:project)
227 end
227 end
228
228
229 def test_show_by_identifier
229 def test_show_by_identifier
230 get :show, :id => 'ecookbook'
230 get :show, :id => 'ecookbook'
231 assert_response :success
231 assert_response :success
232 assert_template 'show'
232 assert_template 'show'
233 assert_not_nil assigns(:project)
233 assert_not_nil assigns(:project)
234 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
234 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
235 end
235 end
236
236
237 def test_show_should_not_fail_when_custom_values_are_nil
237 def test_show_should_not_fail_when_custom_values_are_nil
238 project = Project.find_by_identifier('ecookbook')
238 project = Project.find_by_identifier('ecookbook')
239 project.custom_values.first.update_attribute(:value, nil)
239 project.custom_values.first.update_attribute(:value, nil)
240 get :show, :id => 'ecookbook'
240 get :show, :id => 'ecookbook'
241 assert_response :success
241 assert_response :success
242 assert_template 'show'
242 assert_template 'show'
243 assert_not_nil assigns(:project)
243 assert_not_nil assigns(:project)
244 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
244 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
245 end
245 end
246
246
247 def test_private_subprojects_hidden
247 def test_private_subprojects_hidden
248 get :show, :id => 'ecookbook'
248 get :show, :id => 'ecookbook'
249 assert_response :success
249 assert_response :success
250 assert_template 'show'
250 assert_template 'show'
251 assert_no_tag :tag => 'a', :content => /Private child/
251 assert_no_tag :tag => 'a', :content => /Private child/
252 end
252 end
253
253
254 def test_private_subprojects_visible
254 def test_private_subprojects_visible
255 @request.session[:user_id] = 2 # manager who is a member of the private subproject
255 @request.session[:user_id] = 2 # manager who is a member of the private subproject
256 get :show, :id => 'ecookbook'
256 get :show, :id => 'ecookbook'
257 assert_response :success
257 assert_response :success
258 assert_template 'show'
258 assert_template 'show'
259 assert_tag :tag => 'a', :content => /Private child/
259 assert_tag :tag => 'a', :content => /Private child/
260 end
260 end
261
261
262 def test_settings
262 def test_settings
263 @request.session[:user_id] = 2 # manager
263 @request.session[:user_id] = 2 # manager
264 get :settings, :id => 1
264 get :settings, :id => 1
265 assert_response :success
265 assert_response :success
266 assert_template 'settings'
266 assert_template 'settings'
267 end
267 end
268
268
269 def test_edit
269 def test_edit
270 @request.session[:user_id] = 2 # manager
270 @request.session[:user_id] = 2 # manager
271 post :edit, :id => 1, :project => {:name => 'Test changed name',
271 post :edit, :id => 1, :project => {:name => 'Test changed name',
272 :issue_custom_field_ids => ['']}
272 :issue_custom_field_ids => ['']}
273 assert_redirected_to 'projects/ecookbook/settings'
273 assert_redirected_to 'projects/ecookbook/settings'
274 project = Project.find(1)
274 project = Project.find(1)
275 assert_equal 'Test changed name', project.name
275 assert_equal 'Test changed name', project.name
276 end
276 end
277
277
278 def test_get_destroy
278 def test_get_destroy
279 @request.session[:user_id] = 1 # admin
279 @request.session[:user_id] = 1 # admin
280 get :destroy, :id => 1
280 get :destroy, :id => 1
281 assert_response :success
281 assert_response :success
282 assert_template 'destroy'
282 assert_template 'destroy'
283 assert_not_nil Project.find_by_id(1)
283 assert_not_nil Project.find_by_id(1)
284 end
284 end
285
285
286 def test_post_destroy
286 def test_post_destroy
287 @request.session[:user_id] = 1 # admin
287 @request.session[:user_id] = 1 # admin
288 post :destroy, :id => 1, :confirm => 1
288 post :destroy, :id => 1, :confirm => 1
289 assert_redirected_to 'admin/projects'
289 assert_redirected_to 'admin/projects'
290 assert_nil Project.find_by_id(1)
290 assert_nil Project.find_by_id(1)
291 end
291 end
292
292
293 def test_add_file
293 def test_add_file
294 set_tmp_attachments_directory
294 set_tmp_attachments_directory
295 @request.session[:user_id] = 2
295 @request.session[:user_id] = 2
296 Setting.notified_events = ['file_added']
296 Setting.notified_events = ['file_added']
297 ActionMailer::Base.deliveries.clear
297 ActionMailer::Base.deliveries.clear
298
298
299 assert_difference 'Attachment.count' do
299 assert_difference 'Attachment.count' do
300 post :add_file, :id => 1, :version_id => '',
300 post :add_file, :id => 1, :version_id => '',
301 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
301 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
302 end
302 end
303 assert_redirected_to 'projects/ecookbook/files'
303 assert_redirected_to 'projects/ecookbook/files'
304 a = Attachment.find(:first, :order => 'created_on DESC')
304 a = Attachment.find(:first, :order => 'created_on DESC')
305 assert_equal 'testfile.txt', a.filename
305 assert_equal 'testfile.txt', a.filename
306 assert_equal Project.find(1), a.container
306 assert_equal Project.find(1), a.container
307
307
308 mail = ActionMailer::Base.deliveries.last
308 mail = ActionMailer::Base.deliveries.last
309 assert_kind_of TMail::Mail, mail
309 assert_kind_of TMail::Mail, mail
310 assert_equal "[eCookbook] New file", mail.subject
310 assert_equal "[eCookbook] New file", mail.subject
311 assert mail.body.include?('testfile.txt')
311 assert mail.body.include?('testfile.txt')
312 end
312 end
313
313
314 def test_add_version_file
314 def test_add_version_file
315 set_tmp_attachments_directory
315 set_tmp_attachments_directory
316 @request.session[:user_id] = 2
316 @request.session[:user_id] = 2
317 Setting.notified_events = ['file_added']
317 Setting.notified_events = ['file_added']
318
318
319 assert_difference 'Attachment.count' do
319 assert_difference 'Attachment.count' do
320 post :add_file, :id => 1, :version_id => '2',
320 post :add_file, :id => 1, :version_id => '2',
321 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
321 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
322 end
322 end
323 assert_redirected_to 'projects/ecookbook/files'
323 assert_redirected_to 'projects/ecookbook/files'
324 a = Attachment.find(:first, :order => 'created_on DESC')
324 a = Attachment.find(:first, :order => 'created_on DESC')
325 assert_equal 'testfile.txt', a.filename
325 assert_equal 'testfile.txt', a.filename
326 assert_equal Version.find(2), a.container
326 assert_equal Version.find(2), a.container
327 end
327 end
328
328
329 def test_list_files
329 def test_list_files
330 get :list_files, :id => 1
330 get :list_files, :id => 1
331 assert_response :success
331 assert_response :success
332 assert_template 'list_files'
332 assert_template 'list_files'
333 assert_not_nil assigns(:containers)
333 assert_not_nil assigns(:containers)
334
334
335 # file attached to the project
335 # file attached to the project
336 assert_tag :a, :content => 'project_file.zip',
336 assert_tag :a, :content => 'project_file.zip',
337 :attributes => { :href => '/attachments/download/8/project_file.zip' }
337 :attributes => { :href => '/attachments/download/8/project_file.zip' }
338
338
339 # file attached to a project's version
339 # file attached to a project's version
340 assert_tag :a, :content => 'version_file.zip',
340 assert_tag :a, :content => 'version_file.zip',
341 :attributes => { :href => '/attachments/download/9/version_file.zip' }
341 :attributes => { :href => '/attachments/download/9/version_file.zip' }
342 end
342 end
343
343
344 def test_roadmap
344 def test_roadmap
345 get :roadmap, :id => 1
345 get :roadmap, :id => 1
346 assert_response :success
346 assert_response :success
347 assert_template 'roadmap'
347 assert_template 'roadmap'
348 assert_not_nil assigns(:versions)
348 assert_not_nil assigns(:versions)
349 # Version with no date set appears
349 # Version with no date set appears
350 assert assigns(:versions).include?(Version.find(3))
350 assert assigns(:versions).include?(Version.find(3))
351 # Completed version doesn't appear
351 # Completed version doesn't appear
352 assert !assigns(:versions).include?(Version.find(1))
352 assert !assigns(:versions).include?(Version.find(1))
353 end
353 end
354
354
355 def test_roadmap_with_completed_versions
355 def test_roadmap_with_completed_versions
356 get :roadmap, :id => 1, :completed => 1
356 get :roadmap, :id => 1, :completed => 1
357 assert_response :success
357 assert_response :success
358 assert_template 'roadmap'
358 assert_template 'roadmap'
359 assert_not_nil assigns(:versions)
359 assert_not_nil assigns(:versions)
360 # Version with no date set appears
360 # Version with no date set appears
361 assert assigns(:versions).include?(Version.find(3))
361 assert assigns(:versions).include?(Version.find(3))
362 # Completed version appears
362 # Completed version appears
363 assert assigns(:versions).include?(Version.find(1))
363 assert assigns(:versions).include?(Version.find(1))
364 end
364 end
365
365
366 def test_roadmap_showing_subprojects_versions
366 def test_roadmap_showing_subprojects_versions
367 get :roadmap, :id => 1, :with_subprojects => 1
367 get :roadmap, :id => 1, :with_subprojects => 1
368 assert_response :success
368 assert_response :success
369 assert_template 'roadmap'
369 assert_template 'roadmap'
370 assert_not_nil assigns(:versions)
370 assert_not_nil assigns(:versions)
371 # Version on subproject appears
371 # Version on subproject appears
372 assert assigns(:versions).include?(Version.find(4))
372 assert assigns(:versions).include?(Version.find(4))
373 end
373 end
374 def test_project_activity
374 def test_project_activity
375 get :activity, :id => 1, :with_subprojects => 0
375 get :activity, :id => 1, :with_subprojects => 0
376 assert_response :success
376 assert_response :success
377 assert_template 'activity'
377 assert_template 'activity'
378 assert_not_nil assigns(:events_by_day)
378 assert_not_nil assigns(:events_by_day)
379
379
380 assert_tag :tag => "h3",
380 assert_tag :tag => "h3",
381 :content => /#{2.days.ago.to_date.day}/,
381 :content => /#{2.days.ago.to_date.day}/,
382 :sibling => { :tag => "dl",
382 :sibling => { :tag => "dl",
383 :child => { :tag => "dt",
383 :child => { :tag => "dt",
384 :attributes => { :class => /issue-edit/ },
384 :attributes => { :class => /issue-edit/ },
385 :child => { :tag => "a",
385 :child => { :tag => "a",
386 :content => /(#{IssueStatus.find(2).name})/,
386 :content => /(#{IssueStatus.find(2).name})/,
387 }
387 }
388 }
388 }
389 }
389 }
390 end
390 end
391
391
392 def test_previous_project_activity
392 def test_previous_project_activity
393 get :activity, :id => 1, :from => 3.days.ago.to_date
393 get :activity, :id => 1, :from => 3.days.ago.to_date
394 assert_response :success
394 assert_response :success
395 assert_template 'activity'
395 assert_template 'activity'
396 assert_not_nil assigns(:events_by_day)
396 assert_not_nil assigns(:events_by_day)
397
397
398 assert_tag :tag => "h3",
398 assert_tag :tag => "h3",
399 :content => /#{3.day.ago.to_date.day}/,
399 :content => /#{3.day.ago.to_date.day}/,
400 :sibling => { :tag => "dl",
400 :sibling => { :tag => "dl",
401 :child => { :tag => "dt",
401 :child => { :tag => "dt",
402 :attributes => { :class => /issue/ },
402 :attributes => { :class => /issue/ },
403 :child => { :tag => "a",
403 :child => { :tag => "a",
404 :content => /#{Issue.find(1).subject}/,
404 :content => /#{Issue.find(1).subject}/,
405 }
405 }
406 }
406 }
407 }
407 }
408 end
408 end
409
409
410 def test_global_activity
410 def test_global_activity
411 get :activity
411 get :activity
412 assert_response :success
412 assert_response :success
413 assert_template 'activity'
413 assert_template 'activity'
414 assert_not_nil assigns(:events_by_day)
414 assert_not_nil assigns(:events_by_day)
415
415
416 assert_tag :tag => "h3",
416 assert_tag :tag => "h3",
417 :content => /#{5.day.ago.to_date.day}/,
417 :content => /#{5.day.ago.to_date.day}/,
418 :sibling => { :tag => "dl",
418 :sibling => { :tag => "dl",
419 :child => { :tag => "dt",
419 :child => { :tag => "dt",
420 :attributes => { :class => /issue/ },
420 :attributes => { :class => /issue/ },
421 :child => { :tag => "a",
421 :child => { :tag => "a",
422 :content => /#{Issue.find(5).subject}/,
422 :content => /#{Issue.find(5).subject}/,
423 }
423 }
424 }
424 }
425 }
425 }
426 end
426 end
427
427
428 def test_user_activity
428 def test_user_activity
429 get :activity, :user_id => 2
429 get :activity, :user_id => 2
430 assert_response :success
430 assert_response :success
431 assert_template 'activity'
431 assert_template 'activity'
432 assert_not_nil assigns(:events_by_day)
432 assert_not_nil assigns(:events_by_day)
433
433
434 assert_tag :tag => "h3",
434 assert_tag :tag => "h3",
435 :content => /#{3.day.ago.to_date.day}/,
435 :content => /#{3.day.ago.to_date.day}/,
436 :sibling => { :tag => "dl",
436 :sibling => { :tag => "dl",
437 :child => { :tag => "dt",
437 :child => { :tag => "dt",
438 :attributes => { :class => /issue/ },
438 :attributes => { :class => /issue/ },
439 :child => { :tag => "a",
439 :child => { :tag => "a",
440 :content => /#{Issue.find(1).subject}/,
440 :content => /#{Issue.find(1).subject}/,
441 }
441 }
442 }
442 }
443 }
443 }
444 end
444 end
445
445
446 def test_activity_atom_feed
446 def test_activity_atom_feed
447 get :activity, :format => 'atom'
447 get :activity, :format => 'atom'
448 assert_response :success
448 assert_response :success
449 assert_template 'common/feed.atom.rxml'
449 assert_template 'common/feed.atom.rxml'
450 assert_tag :tag => 'entry', :child => {
451 :tag => 'link',
452 :attributes => {:href => 'http://test.host/issues/11'}}
450 end
453 end
451
454
452 def test_archive
455 def test_archive
453 @request.session[:user_id] = 1 # admin
456 @request.session[:user_id] = 1 # admin
454 post :archive, :id => 1
457 post :archive, :id => 1
455 assert_redirected_to 'admin/projects'
458 assert_redirected_to 'admin/projects'
456 assert !Project.find(1).active?
459 assert !Project.find(1).active?
457 end
460 end
458
461
459 def test_unarchive
462 def test_unarchive
460 @request.session[:user_id] = 1 # admin
463 @request.session[:user_id] = 1 # admin
461 Project.find(1).archive
464 Project.find(1).archive
462 post :unarchive, :id => 1
465 post :unarchive, :id => 1
463 assert_redirected_to 'admin/projects'
466 assert_redirected_to 'admin/projects'
464 assert Project.find(1).active?
467 assert Project.find(1).active?
465 end
468 end
466
469
467 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
470 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
468 CustomField.delete_all
471 CustomField.delete_all
469 parent = nil
472 parent = nil
470 6.times do |i|
473 6.times do |i|
471 p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
474 p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
472 p.set_parent!(parent)
475 p.set_parent!(parent)
473 get :show, :id => p
476 get :show, :id => p
474 assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
477 assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
475 :children => { :count => [i, 3].min,
478 :children => { :count => [i, 3].min,
476 :only => { :tag => 'a' } }
479 :only => { :tag => 'a' } }
477
480
478 parent = p
481 parent = p
479 end
482 end
480 end
483 end
481
484
482 def test_copy_with_project
485 def test_copy_with_project
483 @request.session[:user_id] = 1 # admin
486 @request.session[:user_id] = 1 # admin
484 get :copy, :id => 1
487 get :copy, :id => 1
485 assert_response :success
488 assert_response :success
486 assert_template 'copy'
489 assert_template 'copy'
487 assert assigns(:project)
490 assert assigns(:project)
488 assert_equal Project.find(1).description, assigns(:project).description
491 assert_equal Project.find(1).description, assigns(:project).description
489 assert_nil assigns(:project).id
492 assert_nil assigns(:project).id
490 end
493 end
491
494
492 def test_copy_without_project
495 def test_copy_without_project
493 @request.session[:user_id] = 1 # admin
496 @request.session[:user_id] = 1 # admin
494 get :copy
497 get :copy
495 assert_response :redirect
498 assert_response :redirect
496 assert_redirected_to :controller => 'admin', :action => 'projects'
499 assert_redirected_to :controller => 'admin', :action => 'projects'
497 end
500 end
498
501
499 def test_jump_should_redirect_to_active_tab
502 def test_jump_should_redirect_to_active_tab
500 get :show, :id => 1, :jump => 'issues'
503 get :show, :id => 1, :jump => 'issues'
501 assert_redirected_to 'projects/ecookbook/issues'
504 assert_redirected_to 'projects/ecookbook/issues'
502 end
505 end
503
506
504 def test_jump_should_not_redirect_to_inactive_tab
507 def test_jump_should_not_redirect_to_inactive_tab
505 get :show, :id => 3, :jump => 'documents'
508 get :show, :id => 3, :jump => 'documents'
506 assert_response :success
509 assert_response :success
507 assert_template 'show'
510 assert_template 'show'
508 end
511 end
509
512
510 def test_jump_should_not_redirect_to_unknown_tab
513 def test_jump_should_not_redirect_to_unknown_tab
511 get :show, :id => 3, :jump => 'foobar'
514 get :show, :id => 3, :jump => 'foobar'
512 assert_response :success
515 assert_response :success
513 assert_template 'show'
516 assert_template 'show'
514 end
517 end
515
518
516 def test_reset_activities
519 def test_reset_activities
517 @request.session[:user_id] = 2 # manager
520 @request.session[:user_id] = 2 # manager
518 project_activity = TimeEntryActivity.new({
521 project_activity = TimeEntryActivity.new({
519 :name => 'Project Specific',
522 :name => 'Project Specific',
520 :parent => TimeEntryActivity.find(:first),
523 :parent => TimeEntryActivity.find(:first),
521 :project => Project.find(1),
524 :project => Project.find(1),
522 :active => true
525 :active => true
523 })
526 })
524 assert project_activity.save
527 assert project_activity.save
525 project_activity_two = TimeEntryActivity.new({
528 project_activity_two = TimeEntryActivity.new({
526 :name => 'Project Specific Two',
529 :name => 'Project Specific Two',
527 :parent => TimeEntryActivity.find(:last),
530 :parent => TimeEntryActivity.find(:last),
528 :project => Project.find(1),
531 :project => Project.find(1),
529 :active => true
532 :active => true
530 })
533 })
531 assert project_activity_two.save
534 assert project_activity_two.save
532
535
533 delete :reset_activities, :id => 1
536 delete :reset_activities, :id => 1
534 assert_response :redirect
537 assert_response :redirect
535 assert_redirected_to 'projects/ecookbook/settings/activities'
538 assert_redirected_to 'projects/ecookbook/settings/activities'
536
539
537 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
540 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
538 assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
541 assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
539 end
542 end
540
543
541 def test_reset_activities_should_reassign_time_entries_back_to_the_system_activity
544 def test_reset_activities_should_reassign_time_entries_back_to_the_system_activity
542 @request.session[:user_id] = 2 # manager
545 @request.session[:user_id] = 2 # manager
543 project_activity = TimeEntryActivity.new({
546 project_activity = TimeEntryActivity.new({
544 :name => 'Project Specific Design',
547 :name => 'Project Specific Design',
545 :parent => TimeEntryActivity.find(9),
548 :parent => TimeEntryActivity.find(9),
546 :project => Project.find(1),
549 :project => Project.find(1),
547 :active => true
550 :active => true
548 })
551 })
549 assert project_activity.save
552 assert project_activity.save
550 assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
553 assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
551 assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
554 assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
552
555
553 delete :reset_activities, :id => 1
556 delete :reset_activities, :id => 1
554 assert_response :redirect
557 assert_response :redirect
555 assert_redirected_to 'projects/ecookbook/settings/activities'
558 assert_redirected_to 'projects/ecookbook/settings/activities'
556
559
557 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
560 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
558 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity"
561 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size, "TimeEntries still assigned to project specific activity"
559 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
562 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
560 end
563 end
561
564
562 def test_save_activities_to_override_system_activities
565 def test_save_activities_to_override_system_activities
563 @request.session[:user_id] = 2 # manager
566 @request.session[:user_id] = 2 # manager
564 billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
567 billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
565
568
566 post :save_activities, :id => 1, :enumerations => {
569 post :save_activities, :id => 1, :enumerations => {
567 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate
570 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate
568 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
571 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
569 "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
572 "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
570 "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
573 "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
571 }
574 }
572
575
573 assert_response :redirect
576 assert_response :redirect
574 assert_redirected_to 'projects/ecookbook/settings/activities'
577 assert_redirected_to 'projects/ecookbook/settings/activities'
575
578
576 # Created project specific activities...
579 # Created project specific activities...
577 project = Project.find('ecookbook')
580 project = Project.find('ecookbook')
578
581
579 # ... Design
582 # ... Design
580 design = project.time_entry_activities.find_by_name("Design")
583 design = project.time_entry_activities.find_by_name("Design")
581 assert design, "Project activity not found"
584 assert design, "Project activity not found"
582
585
583 assert_equal 9, design.parent_id # Relate to the system activity
586 assert_equal 9, design.parent_id # Relate to the system activity
584 assert_not_equal design.parent.id, design.id # Different records
587 assert_not_equal design.parent.id, design.id # Different records
585 assert_equal design.parent.name, design.name # Same name
588 assert_equal design.parent.name, design.name # Same name
586 assert !design.active?
589 assert !design.active?
587
590
588 # ... Development
591 # ... Development
589 development = project.time_entry_activities.find_by_name("Development")
592 development = project.time_entry_activities.find_by_name("Development")
590 assert development, "Project activity not found"
593 assert development, "Project activity not found"
591
594
592 assert_equal 10, development.parent_id # Relate to the system activity
595 assert_equal 10, development.parent_id # Relate to the system activity
593 assert_not_equal development.parent.id, development.id # Different records
596 assert_not_equal development.parent.id, development.id # Different records
594 assert_equal development.parent.name, development.name # Same name
597 assert_equal development.parent.name, development.name # Same name
595 assert development.active?
598 assert development.active?
596 assert_equal "0", development.custom_value_for(billable_field).value
599 assert_equal "0", development.custom_value_for(billable_field).value
597
600
598 # ... Inactive Activity
601 # ... Inactive Activity
599 previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
602 previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
600 assert previously_inactive, "Project activity not found"
603 assert previously_inactive, "Project activity not found"
601
604
602 assert_equal 14, previously_inactive.parent_id # Relate to the system activity
605 assert_equal 14, previously_inactive.parent_id # Relate to the system activity
603 assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
606 assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
604 assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
607 assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
605 assert previously_inactive.active?
608 assert previously_inactive.active?
606 assert_equal "1", previously_inactive.custom_value_for(billable_field).value
609 assert_equal "1", previously_inactive.custom_value_for(billable_field).value
607
610
608 # ... QA
611 # ... QA
609 assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
612 assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
610 end
613 end
611
614
612 def test_save_activities_will_update_project_specific_activities
615 def test_save_activities_will_update_project_specific_activities
613 @request.session[:user_id] = 2 # manager
616 @request.session[:user_id] = 2 # manager
614
617
615 project_activity = TimeEntryActivity.new({
618 project_activity = TimeEntryActivity.new({
616 :name => 'Project Specific',
619 :name => 'Project Specific',
617 :parent => TimeEntryActivity.find(:first),
620 :parent => TimeEntryActivity.find(:first),
618 :project => Project.find(1),
621 :project => Project.find(1),
619 :active => true
622 :active => true
620 })
623 })
621 assert project_activity.save
624 assert project_activity.save
622 project_activity_two = TimeEntryActivity.new({
625 project_activity_two = TimeEntryActivity.new({
623 :name => 'Project Specific Two',
626 :name => 'Project Specific Two',
624 :parent => TimeEntryActivity.find(:last),
627 :parent => TimeEntryActivity.find(:last),
625 :project => Project.find(1),
628 :project => Project.find(1),
626 :active => true
629 :active => true
627 })
630 })
628 assert project_activity_two.save
631 assert project_activity_two.save
629
632
630
633
631 post :save_activities, :id => 1, :enumerations => {
634 post :save_activities, :id => 1, :enumerations => {
632 project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate
635 project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate
633 project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
636 project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
634 }
637 }
635
638
636 assert_response :redirect
639 assert_response :redirect
637 assert_redirected_to 'projects/ecookbook/settings/activities'
640 assert_redirected_to 'projects/ecookbook/settings/activities'
638
641
639 # Created project specific activities...
642 # Created project specific activities...
640 project = Project.find('ecookbook')
643 project = Project.find('ecookbook')
641 assert_equal 2, project.time_entry_activities.count
644 assert_equal 2, project.time_entry_activities.count
642
645
643 activity_one = project.time_entry_activities.find_by_name(project_activity.name)
646 activity_one = project.time_entry_activities.find_by_name(project_activity.name)
644 assert activity_one, "Project activity not found"
647 assert activity_one, "Project activity not found"
645 assert_equal project_activity.id, activity_one.id
648 assert_equal project_activity.id, activity_one.id
646 assert !activity_one.active?
649 assert !activity_one.active?
647
650
648 activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
651 activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
649 assert activity_two, "Project activity not found"
652 assert activity_two, "Project activity not found"
650 assert_equal project_activity_two.id, activity_two.id
653 assert_equal project_activity_two.id, activity_two.id
651 assert !activity_two.active?
654 assert !activity_two.active?
652 end
655 end
653
656
654 def test_save_activities_when_creating_new_activities_will_convert_existing_data
657 def test_save_activities_when_creating_new_activities_will_convert_existing_data
655 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
658 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
656
659
657 @request.session[:user_id] = 2 # manager
660 @request.session[:user_id] = 2 # manager
658 post :save_activities, :id => 1, :enumerations => {
661 post :save_activities, :id => 1, :enumerations => {
659 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate
662 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate
660 }
663 }
661 assert_response :redirect
664 assert_response :redirect
662
665
663 # No more TimeEntries using the system activity
666 # No more TimeEntries using the system activity
664 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities"
667 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities"
665 # All TimeEntries using project activity
668 # All TimeEntries using project activity
666 project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
669 project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
667 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"
670 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"
668 end
671 end
669
672
670 def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
673 def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
671 # TODO: Need to cause an exception on create but these tests
674 # TODO: Need to cause an exception on create but these tests
672 # aren't setup for mocking. Just create a record now so the
675 # aren't setup for mocking. Just create a record now so the
673 # second one is a dupicate
676 # second one is a dupicate
674 parent = TimeEntryActivity.find(9)
677 parent = TimeEntryActivity.find(9)
675 TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true})
678 TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true})
676 TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
679 TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
677
680
678 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
681 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
679 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
682 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
680
683
681 @request.session[:user_id] = 2 # manager
684 @request.session[:user_id] = 2 # manager
682 post :save_activities, :id => 1, :enumerations => {
685 post :save_activities, :id => 1, :enumerations => {
683 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
686 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
684 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
687 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
685 }
688 }
686 assert_response :redirect
689 assert_response :redirect
687
690
688 # TimeEntries shouldn't have been reassigned on the failed record
691 # TimeEntries shouldn't have been reassigned on the failed record
689 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
692 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
690 # TimeEntries shouldn't have been reassigned on the saved record either
693 # TimeEntries shouldn't have been reassigned on the saved record either
691 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities"
694 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities"
692 end
695 end
693
696
694 # A hook that is manually registered later
697 # A hook that is manually registered later
695 class ProjectBasedTemplate < Redmine::Hook::ViewListener
698 class ProjectBasedTemplate < Redmine::Hook::ViewListener
696 def view_layouts_base_html_head(context)
699 def view_layouts_base_html_head(context)
697 # Adds a project stylesheet
700 # Adds a project stylesheet
698 stylesheet_link_tag(context[:project].identifier) if context[:project]
701 stylesheet_link_tag(context[:project].identifier) if context[:project]
699 end
702 end
700 end
703 end
701 # Don't use this hook now
704 # Don't use this hook now
702 Redmine::Hook.clear_listeners
705 Redmine::Hook.clear_listeners
703
706
704 def test_hook_response
707 def test_hook_response
705 Redmine::Hook.add_listener(ProjectBasedTemplate)
708 Redmine::Hook.add_listener(ProjectBasedTemplate)
706 get :show, :id => 1
709 get :show, :id => 1
707 assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
710 assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
708 :parent => {:tag => 'head'}
711 :parent => {:tag => 'head'}
709
712
710 Redmine::Hook.clear_listeners
713 Redmine::Hook.clear_listeners
711 end
714 end
712 end
715 end
@@ -1,91 +1,91
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
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
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.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module Redmine
18 module Redmine
19 module Acts
19 module Acts
20 module Event
20 module Event
21 def self.included(base)
21 def self.included(base)
22 base.extend ClassMethods
22 base.extend ClassMethods
23 end
23 end
24
24
25 module ClassMethods
25 module ClassMethods
26 def acts_as_event(options = {})
26 def acts_as_event(options = {})
27 return if self.included_modules.include?(Redmine::Acts::Event::InstanceMethods)
27 return if self.included_modules.include?(Redmine::Acts::Event::InstanceMethods)
28 default_options = { :datetime => :created_on,
28 default_options = { :datetime => :created_on,
29 :title => :title,
29 :title => :title,
30 :description => :description,
30 :description => :description,
31 :author => :author,
31 :author => :author,
32 :url => {:controller => 'welcome'},
32 :url => {:controller => 'welcome'},
33 :type => self.name.underscore.dasherize }
33 :type => self.name.underscore.dasherize }
34
34
35 cattr_accessor :event_options
35 cattr_accessor :event_options
36 self.event_options = default_options.merge(options)
36 self.event_options = default_options.merge(options)
37 send :include, Redmine::Acts::Event::InstanceMethods
37 send :include, Redmine::Acts::Event::InstanceMethods
38 end
38 end
39 end
39 end
40
40
41 module InstanceMethods
41 module InstanceMethods
42 def self.included(base)
42 def self.included(base)
43 base.extend ClassMethods
43 base.extend ClassMethods
44 end
44 end
45
45
46 %w(datetime title description author type).each do |attr|
46 %w(datetime title description author type).each do |attr|
47 src = <<-END_SRC
47 src = <<-END_SRC
48 def event_#{attr}
48 def event_#{attr}
49 option = event_options[:#{attr}]
49 option = event_options[:#{attr}]
50 if option.is_a?(Proc)
50 if option.is_a?(Proc)
51 option.call(self)
51 option.call(self)
52 elsif option.is_a?(Symbol)
52 elsif option.is_a?(Symbol)
53 send(option)
53 send(option)
54 else
54 else
55 option
55 option
56 end
56 end
57 end
57 end
58 END_SRC
58 END_SRC
59 class_eval src, __FILE__, __LINE__
59 class_eval src, __FILE__, __LINE__
60 end
60 end
61
61
62 def event_date
62 def event_date
63 event_datetime.to_date
63 event_datetime.to_date
64 end
64 end
65
65
66 def event_url(options = {})
66 def event_url(options = {})
67 option = event_options[:url]
67 option = event_options[:url]
68 if option.is_a?(Proc)
68 if option.is_a?(Proc)
69 option.call(self)
69 option.call(self).merge(options)
70 elsif option.is_a?(Hash)
70 elsif option.is_a?(Hash)
71 option.merge(options)
71 option.merge(options)
72 elsif option.is_a?(Symbol)
72 elsif option.is_a?(Symbol)
73 send(option)
73 send(option).merge(options)
74 else
74 else
75 option
75 option
76 end
76 end
77 end
77 end
78
78
79 # Returns the mail adresses of users that should be notified
79 # Returns the mail adresses of users that should be notified
80 def recipients
80 def recipients
81 notified = project.notified_users
81 notified = project.notified_users
82 notified.reject! {|user| !visible?(user)}
82 notified.reject! {|user| !visible?(user)}
83 notified.collect(&:mail)
83 notified.collect(&:mail)
84 end
84 end
85
85
86 module ClassMethods
86 module ClassMethods
87 end
87 end
88 end
88 end
89 end
89 end
90 end
90 end
91 end
91 end
General Comments 0
You need to be logged in to leave comments. Login now