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