1 # Redmine - project management software
2 # Copyright (C) 2006-2008 Jean-Philippe Lang
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'projects_controller'
21 # Re-raise errors caught by the controller.
22 class ProjectsController; def rescue_action(e) raise e end; end
24 class ProjectsControllerTest < ActionController::TestCase
25 fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
26 :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
27 :attachments, :custom_fields, :custom_values, :time_entries
30 @controller = ProjectsController.new
31 @request = ActionController::TestRequest.new
32 @response = ActionController::TestResponse.new
33 @request.session[:user_id] = nil
34 Setting.default_language = 'en'
37 def test_index_routing
39 {:method => :get, :path => '/projects'},
40 :controller => 'projects', :action => 'index'
46 assert_response :success
47 assert_template 'index'
48 assert_not_nil assigns(:projects)
50 assert_tag :ul, :child => {:tag => 'li',
51 :descendant => {:tag => 'a', :content => 'eCookbook'},
52 :child => { :tag => 'ul',
53 :descendant => { :tag => 'a',
54 :content => 'Child of private child'
59 assert_no_tag :a, :content => /Private child of eCookbook/
62 def test_index_atom_routing
64 {:method => :get, :path => '/projects.atom'},
65 :controller => 'projects', :action => 'index', :format => 'atom'
70 get :index, :format => 'atom'
71 assert_response :success
72 assert_template 'common/feed.atom.rxml'
73 assert_select 'feed>title', :text => 'Redmine: Latest projects'
74 assert_select 'feed>entry', :count => Project.count(:conditions => Project.visible_by(User.current))
79 {:method => :get, :path => '/projects/new'},
80 :controller => 'projects', :action => 'add'
83 {:controller => 'projects', :action => 'add'},
84 {:method => :post, :path => '/projects/new'}
87 {:controller => 'projects', :action => 'add'},
88 {:method => :post, :path => '/projects'}
93 context "by admin user" do
95 @request.session[:user_id] = 1
98 should "accept get" do
100 assert_response :success
101 assert_template 'add'
104 should "accept post" do
105 post :add, :project => { :name => "blog",
106 :description => "weblog",
107 :identifier => "blog",
109 :custom_field_values => { '3' => 'Beta' }
111 assert_redirected_to '/projects/blog/settings'
113 project = Project.find_by_name('blog')
114 assert_kind_of Project, project
115 assert_equal 'weblog', project.description
116 assert_equal true, project.is_public?
117 assert_nil project.parent
120 should "accept post with parent" do
121 post :add, :project => { :name => "blog",
122 :description => "weblog",
123 :identifier => "blog",
125 :custom_field_values => { '3' => 'Beta' },
128 assert_redirected_to '/projects/blog/settings'
130 project = Project.find_by_name('blog')
131 assert_kind_of Project, project
132 assert_equal Project.find(1), project.parent
136 context "by non-admin user with add_project permission" do
138 Role.non_member.add_permission! :add_project
139 @request.session[:user_id] = 9
142 should "accept get" do
144 assert_response :success
145 assert_template 'add'
146 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'}
149 should "accept post" do
150 post :add, :project => { :name => "blog",
151 :description => "weblog",
152 :identifier => "blog",
154 :custom_field_values => { '3' => 'Beta' }
157 assert_redirected_to '/projects/blog/settings'
159 project = Project.find_by_name('blog')
160 assert_kind_of Project, project
161 assert_equal 'weblog', project.description
162 assert_equal true, project.is_public?
164 # User should be added as a project member
165 assert User.find(9).member_of?(project)
166 assert_equal 1, project.members.size
169 should "fail with parent_id" do
170 assert_no_difference 'Project.count' do
171 post :add, :project => { :name => "blog",
172 :description => "weblog",
173 :identifier => "blog",
175 :custom_field_values => { '3' => 'Beta' },
179 assert_response :success
180 project = assigns(:project)
181 assert_kind_of Project, project
182 assert_not_nil project.errors.on(:parent_id)
186 context "by non-admin user with add_subprojects permission" do
188 Role.find(1).remove_permission! :add_project
189 Role.find(1).add_permission! :add_subprojects
190 @request.session[:user_id] = 2
193 should "accept get" do
194 get :add, :parent_id => 'ecookbook'
195 assert_response :success
196 assert_template 'add'
197 # parent project selected
198 assert_tag :select, :attributes => {:name => 'project[parent_id]'},
199 :child => {:tag => 'option', :attributes => {:value => '1', :selected => 'selected'}}
201 assert_no_tag :select, :attributes => {:name => 'project[parent_id]'},
202 :child => {:tag => 'option', :attributes => {:value => ''}}
205 should "accept post with parent_id" do
206 post :add, :project => { :name => "blog",
207 :description => "weblog",
208 :identifier => "blog",
210 :custom_field_values => { '3' => 'Beta' },
213 assert_redirected_to '/projects/blog/settings'
214 project = Project.find_by_name('blog')
217 should "fail without parent_id" do
218 assert_no_difference 'Project.count' do
219 post :add, :project => { :name => "blog",
220 :description => "weblog",
221 :identifier => "blog",
223 :custom_field_values => { '3' => 'Beta' }
226 assert_response :success
227 project = assigns(:project)
228 assert_kind_of Project, project
229 assert_not_nil project.errors.on(:parent_id)
232 should "fail with unauthorized parent_id" do
233 assert !User.find(2).member_of?(Project.find(6))
234 assert_no_difference 'Project.count' do
235 post :add, :project => { :name => "blog",
236 :description => "weblog",
237 :identifier => "blog",
239 :custom_field_values => { '3' => 'Beta' },
243 assert_response :success
244 project = assigns(:project)
245 assert_kind_of Project, project
246 assert_not_nil project.errors.on(:parent_id)
251 def test_show_routing
253 {:method => :get, :path => '/projects/test'},
254 :controller => 'projects', :action => 'show', :id => 'test'
260 assert_response :success
261 assert_template 'show'
262 assert_not_nil assigns(:project)
265 def test_show_by_identifier
266 get :show, :id => 'ecookbook'
267 assert_response :success
268 assert_template 'show'
269 assert_not_nil assigns(:project)
270 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
273 def test_show_should_not_fail_when_custom_values_are_nil
274 project = Project.find_by_identifier('ecookbook')
275 project.custom_values.first.update_attribute(:value, nil)
276 get :show, :id => 'ecookbook'
277 assert_response :success
278 assert_template 'show'
279 assert_not_nil assigns(:project)
280 assert_equal Project.find_by_identifier('ecookbook'), assigns(:project)
283 def test_private_subprojects_hidden
284 get :show, :id => 'ecookbook'
285 assert_response :success
286 assert_template 'show'
287 assert_no_tag :tag => 'a', :content => /Private child/
290 def test_private_subprojects_visible
291 @request.session[:user_id] = 2 # manager who is a member of the private subproject
292 get :show, :id => 'ecookbook'
293 assert_response :success
294 assert_template 'show'
295 assert_tag :tag => 'a', :content => /Private child/
298 def test_settings_routing
300 {:method => :get, :path => '/projects/4223/settings'},
301 :controller => 'projects', :action => 'settings', :id => '4223'
304 {:method => :get, :path => '/projects/4223/settings/members'},
305 :controller => 'projects', :action => 'settings', :id => '4223', :tab => 'members'
310 @request.session[:user_id] = 2 # manager
311 get :settings, :id => 1
312 assert_response :success
313 assert_template 'settings'
317 @request.session[:user_id] = 2 # manager
318 post :edit, :id => 1, :project => {:name => 'Test changed name',
319 :issue_custom_field_ids => ['']}
320 assert_redirected_to 'projects/ecookbook/settings'
321 project = Project.find(1)
322 assert_equal 'Test changed name', project.name
325 def test_add_version_routing
327 {:method => :get, :path => 'projects/64/versions/new'},
328 :controller => 'projects', :action => 'add_version', :id => '64'
332 {:method => :post, :path => 'projects/64/versions/new'},
333 :controller => 'projects', :action => 'add_version', :id => '64'
338 @request.session[:user_id] = 2 # manager
339 assert_difference 'Version.count' do
340 post :add_version, :id => '1', :version => {:name => 'test_add_version'}
342 assert_redirected_to '/projects/ecookbook/settings/versions'
343 version = Version.find_by_name('test_add_version')
344 assert_not_nil version
345 assert_equal 1, version.project_id
348 def test_add_version_from_issue_form
349 @request.session[:user_id] = 2 # manager
350 assert_difference 'Version.count' do
351 xhr :post, :add_version, :id => '1', :version => {:name => 'test_add_version_from_issue_form'}
353 assert_response :success
354 assert_select_rjs :replace, 'issue_fixed_version_id'
355 version = Version.find_by_name('test_add_version_from_issue_form')
356 assert_not_nil version
357 assert_equal 1, version.project_id
360 def test_add_issue_category_routing
362 {:method => :get, :path => 'projects/test/categories/new'},
363 :controller => 'projects', :action => 'add_issue_category', :id => 'test'
366 #TODO: use PUT and update form
367 {:method => :post, :path => 'projects/64/categories/new'},
368 :controller => 'projects', :action => 'add_issue_category', :id => '64'
372 def test_destroy_routing
374 {:method => :get, :path => '/projects/567/destroy'},
375 :controller => 'projects', :action => 'destroy', :id => '567'
378 #TODO: use DELETE and update form
379 {:method => :post, :path => 'projects/64/destroy'},
380 :controller => 'projects', :action => 'destroy', :id => '64'
385 @request.session[:user_id] = 1 # admin
386 get :destroy, :id => 1
387 assert_response :success
388 assert_template 'destroy'
389 assert_not_nil Project.find_by_id(1)
392 def test_post_destroy
393 @request.session[:user_id] = 1 # admin
394 post :destroy, :id => 1, :confirm => 1
395 assert_redirected_to 'admin/projects'
396 assert_nil Project.find_by_id(1)
400 set_tmp_attachments_directory
401 @request.session[:user_id] = 2
402 Setting.notified_events = ['file_added']
403 ActionMailer::Base.deliveries.clear
405 assert_difference 'Attachment.count' do
406 post :add_file, :id => 1, :version_id => '',
407 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
409 assert_redirected_to 'projects/ecookbook/files'
410 a = Attachment.find(:first, :order => 'created_on DESC')
411 assert_equal 'testfile.txt', a.filename
412 assert_equal Project.find(1), a.container
414 mail = ActionMailer::Base.deliveries.last
415 assert_kind_of TMail::Mail, mail
416 assert_equal "[eCookbook] New file", mail.subject
417 assert mail.body.include?('testfile.txt')
420 def test_add_file_routing
422 {:method => :get, :path => '/projects/33/files/new'},
423 :controller => 'projects', :action => 'add_file', :id => '33'
426 {:method => :post, :path => '/projects/33/files/new'},
427 :controller => 'projects', :action => 'add_file', :id => '33'
431 def test_add_version_file
432 set_tmp_attachments_directory
433 @request.session[:user_id] = 2
434 Setting.notified_events = ['file_added']
436 assert_difference 'Attachment.count' do
437 post :add_file, :id => 1, :version_id => '2',
438 :attachments => {'1' => {'file' => uploaded_test_file('testfile.txt', 'text/plain')}}
440 assert_redirected_to 'projects/ecookbook/files'
441 a = Attachment.find(:first, :order => 'created_on DESC')
442 assert_equal 'testfile.txt', a.filename
443 assert_equal Version.find(2), a.container
447 get :list_files, :id => 1
448 assert_response :success
449 assert_template 'list_files'
450 assert_not_nil assigns(:containers)
452 # file attached to the project
453 assert_tag :a, :content => 'project_file.zip',
454 :attributes => { :href => '/attachments/download/8/project_file.zip' }
456 # file attached to a project's version
457 assert_tag :a, :content => 'version_file.zip',
458 :attributes => { :href => '/attachments/download/9/version_file.zip' }
461 def test_list_files_routing
463 {:method => :get, :path => '/projects/33/files'},
464 :controller => 'projects', :action => 'list_files', :id => '33'
468 def test_roadmap_routing
470 {:method => :get, :path => 'projects/33/roadmap'},
471 :controller => 'projects', :action => 'roadmap', :id => '33'
476 get :roadmap, :id => 1
477 assert_response :success
478 assert_template 'roadmap'
479 assert_not_nil assigns(:versions)
480 # Version with no date set appears
481 assert assigns(:versions).include?(Version.find(3))
482 # Completed version doesn't appear
483 assert !assigns(:versions).include?(Version.find(1))
486 def test_roadmap_with_completed_versions
487 get :roadmap, :id => 1, :completed => 1
488 assert_response :success
489 assert_template 'roadmap'
490 assert_not_nil assigns(:versions)
491 # Version with no date set appears
492 assert assigns(:versions).include?(Version.find(3))
493 # Completed version appears
494 assert assigns(:versions).include?(Version.find(1))
497 def test_roadmap_showing_subprojects_versions
498 get :roadmap, :id => 1, :with_subprojects => 1
499 assert_response :success
500 assert_template 'roadmap'
501 assert_not_nil assigns(:versions)
502 # Version on subproject appears
503 assert assigns(:versions).include?(Version.find(4))
506 def test_project_activity_routing
508 {:method => :get, :path => '/projects/1/activity'},
509 :controller => 'projects', :action => 'activity', :id => '1'
513 def test_project_activity_atom_routing
515 {:method => :get, :path => '/projects/1/activity.atom'},
516 :controller => 'projects', :action => 'activity', :id => '1', :format => 'atom'
520 def test_project_activity
521 get :activity, :id => 1, :with_subprojects => 0
522 assert_response :success
523 assert_template 'activity'
524 assert_not_nil assigns(:events_by_day)
526 assert_tag :tag => "h3",
527 :content => /#{2.days.ago.to_date.day}/,
528 :sibling => { :tag => "dl",
529 :child => { :tag => "dt",
530 :attributes => { :class => /issue-edit/ },
531 :child => { :tag => "a",
532 :content => /(#{IssueStatus.find(2).name})/,
538 def test_previous_project_activity
539 get :activity, :id => 1, :from => 3.days.ago.to_date
540 assert_response :success
541 assert_template 'activity'
542 assert_not_nil assigns(:events_by_day)
544 assert_tag :tag => "h3",
545 :content => /#{3.day.ago.to_date.day}/,
546 :sibling => { :tag => "dl",
547 :child => { :tag => "dt",
548 :attributes => { :class => /issue/ },
549 :child => { :tag => "a",
550 :content => /#{Issue.find(1).subject}/,
556 def test_global_activity_routing
557 assert_routing({:method => :get, :path => '/activity'}, :controller => 'projects', :action => 'activity', :id => nil)
560 def test_global_activity
562 assert_response :success
563 assert_template 'activity'
564 assert_not_nil assigns(:events_by_day)
566 assert_tag :tag => "h3",
567 :content => /#{5.day.ago.to_date.day}/,
568 :sibling => { :tag => "dl",
569 :child => { :tag => "dt",
570 :attributes => { :class => /issue/ },
571 :child => { :tag => "a",
572 :content => /#{Issue.find(5).subject}/,
578 def test_user_activity
579 get :activity, :user_id => 2
580 assert_response :success
581 assert_template 'activity'
582 assert_not_nil assigns(:events_by_day)
584 assert_tag :tag => "h3",
585 :content => /#{3.day.ago.to_date.day}/,
586 :sibling => { :tag => "dl",
587 :child => { :tag => "dt",
588 :attributes => { :class => /issue/ },
589 :child => { :tag => "a",
590 :content => /#{Issue.find(1).subject}/,
596 def test_global_activity_atom_routing
597 assert_routing({:method => :get, :path => '/activity.atom'}, :controller => 'projects', :action => 'activity', :id => nil, :format => 'atom')
600 def test_activity_atom_feed
601 get :activity, :format => 'atom'
602 assert_response :success
603 assert_template 'common/feed.atom.rxml'
606 def test_archive_routing
608 #TODO: use PUT to project path and modify form
609 {:method => :post, :path => 'projects/64/archive'},
610 :controller => 'projects', :action => 'archive', :id => '64'
615 @request.session[:user_id] = 1 # admin
616 post :archive, :id => 1
617 assert_redirected_to 'admin/projects'
618 assert !Project.find(1).active?
621 def test_unarchive_routing
623 #TODO: use PUT to project path and modify form
624 {:method => :post, :path => '/projects/567/unarchive'},
625 :controller => 'projects', :action => 'unarchive', :id => '567'
630 @request.session[:user_id] = 1 # admin
631 Project.find(1).archive
632 post :unarchive, :id => 1
633 assert_redirected_to 'admin/projects'
634 assert Project.find(1).active?
637 def test_project_breadcrumbs_should_be_limited_to_3_ancestors
638 CustomField.delete_all
641 p = Project.create!(:name => "Breadcrumbs #{i}", :identifier => "breadcrumbs-#{i}")
642 p.set_parent!(parent)
644 assert_tag :h1, :parent => { :attributes => {:id => 'header'}},
645 :children => { :count => [i, 3].min,
646 :only => { :tag => 'a' } }
652 def test_copy_with_project
653 @request.session[:user_id] = 1 # admin
655 assert_response :success
656 assert_template 'copy'
657 assert assigns(:project)
658 assert_equal Project.find(1).description, assigns(:project).description
659 assert_nil assigns(:project).id
662 def test_copy_without_project
663 @request.session[:user_id] = 1 # admin
665 assert_response :redirect
666 assert_redirected_to :controller => 'admin', :action => 'projects'
669 def test_jump_should_redirect_to_active_tab
670 get :show, :id => 1, :jump => 'issues'
671 assert_redirected_to 'projects/ecookbook/issues'
674 def test_jump_should_not_redirect_to_inactive_tab
675 get :show, :id => 3, :jump => 'documents'
676 assert_response :success
677 assert_template 'show'
680 def test_jump_should_not_redirect_to_unknown_tab
681 get :show, :id => 3, :jump => 'foobar'
682 assert_response :success
683 assert_template 'show'
686 def test_reset_activities_routing
687 assert_routing({:method => :delete, :path => 'projects/64/reset_activities'},
688 :controller => 'projects', :action => 'reset_activities', :id => '64')
691 def test_reset_activities
692 @request.session[:user_id] = 2 # manager
693 project_activity = TimeEntryActivity.new({
694 :name => 'Project Specific',
695 :parent => TimeEntryActivity.find(:first),
696 :project => Project.find(1),
699 assert project_activity.save
700 project_activity_two = TimeEntryActivity.new({
701 :name => 'Project Specific Two',
702 :parent => TimeEntryActivity.find(:last),
703 :project => Project.find(1),
706 assert project_activity_two.save
708 delete :reset_activities, :id => 1
709 assert_response :redirect
710 assert_redirected_to 'projects/ecookbook/settings/activities'
712 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
713 assert_nil TimeEntryActivity.find_by_id(project_activity_two.id)
716 def test_reset_activities_should_reassign_time_entries_back_to_the_system_activity
717 @request.session[:user_id] = 2 # manager
718 project_activity = TimeEntryActivity.new({
719 :name => 'Project Specific Design',
720 :parent => TimeEntryActivity.find(9),
721 :project => Project.find(1),
724 assert project_activity.save
725 assert TimeEntry.update_all("activity_id = '#{project_activity.id}'", ["project_id = ? AND activity_id = ?", 1, 9])
726 assert 3, TimeEntry.find_all_by_activity_id_and_project_id(project_activity.id, 1).size
728 delete :reset_activities, :id => 1
729 assert_response :redirect
730 assert_redirected_to 'projects/ecookbook/settings/activities'
732 assert_nil TimeEntryActivity.find_by_id(project_activity.id)
733 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 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "TimeEntries still assigned to project specific activity"
737 def test_save_activities_routing
738 assert_routing({:method => :post, :path => 'projects/64/activities/save'},
739 :controller => 'projects', :action => 'save_activities', :id => '64')
742 def test_save_activities_to_override_system_activities
743 @request.session[:user_id] = 2 # manager
744 billable_field = TimeEntryActivityCustomField.find_by_name("Billable")
746 post :save_activities, :id => 1, :enumerations => {
747 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design, De-activate
748 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"}, # Development, Change custom value
749 "14"=>{"parent_id"=>"14", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"}, # Inactive Activity, Activate with custom value
750 "11"=>{"parent_id"=>"11", "custom_field_values"=>{"7"=>"1"}, "active"=>"1"} # QA, no changes
753 assert_response :redirect
754 assert_redirected_to 'projects/ecookbook/settings/activities'
756 # Created project specific activities...
757 project = Project.find('ecookbook')
760 design = project.time_entry_activities.find_by_name("Design")
761 assert design, "Project activity not found"
763 assert_equal 9, design.parent_id # Relate to the system activity
764 assert_not_equal design.parent.id, design.id # Different records
765 assert_equal design.parent.name, design.name # Same name
766 assert !design.active?
769 development = project.time_entry_activities.find_by_name("Development")
770 assert development, "Project activity not found"
772 assert_equal 10, development.parent_id # Relate to the system activity
773 assert_not_equal development.parent.id, development.id # Different records
774 assert_equal development.parent.name, development.name # Same name
775 assert development.active?
776 assert_equal "0", development.custom_value_for(billable_field).value
778 # ... Inactive Activity
779 previously_inactive = project.time_entry_activities.find_by_name("Inactive Activity")
780 assert previously_inactive, "Project activity not found"
782 assert_equal 14, previously_inactive.parent_id # Relate to the system activity
783 assert_not_equal previously_inactive.parent.id, previously_inactive.id # Different records
784 assert_equal previously_inactive.parent.name, previously_inactive.name # Same name
785 assert previously_inactive.active?
786 assert_equal "1", previously_inactive.custom_value_for(billable_field).value
789 assert_equal nil, project.time_entry_activities.find_by_name("QA"), "Custom QA activity created when it wasn't modified"
792 def test_save_activities_will_update_project_specific_activities
793 @request.session[:user_id] = 2 # manager
795 project_activity = TimeEntryActivity.new({
796 :name => 'Project Specific',
797 :parent => TimeEntryActivity.find(:first),
798 :project => Project.find(1),
801 assert project_activity.save
802 project_activity_two = TimeEntryActivity.new({
803 :name => 'Project Specific Two',
804 :parent => TimeEntryActivity.find(:last),
805 :project => Project.find(1),
808 assert project_activity_two.save
811 post :save_activities, :id => 1, :enumerations => {
812 project_activity.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # De-activate
813 project_activity_two.id => {"custom_field_values"=>{"7" => "1"}, "active"=>"0"} # De-activate
816 assert_response :redirect
817 assert_redirected_to 'projects/ecookbook/settings/activities'
819 # Created project specific activities...
820 project = Project.find('ecookbook')
821 assert_equal 2, project.time_entry_activities.count
823 activity_one = project.time_entry_activities.find_by_name(project_activity.name)
824 assert activity_one, "Project activity not found"
825 assert_equal project_activity.id, activity_one.id
826 assert !activity_one.active?
828 activity_two = project.time_entry_activities.find_by_name(project_activity_two.name)
829 assert activity_two, "Project activity not found"
830 assert_equal project_activity_two.id, activity_two.id
831 assert !activity_two.active?
834 def test_save_activities_when_creating_new_activities_will_convert_existing_data
835 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
837 @request.session[:user_id] = 2 # manager
838 post :save_activities, :id => 1, :enumerations => {
839 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"} # Design, De-activate
841 assert_response :redirect
843 # No more TimeEntries using the system activity
844 assert_equal 0, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries still assigned to system activities"
845 # All TimeEntries using project activity
846 project_specific_activity = TimeEntryActivity.find_by_parent_id_and_project_id(9, 1)
847 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"
850 def test_save_activities_when_creating_new_activities_will_not_convert_existing_data_if_an_exception_is_raised
851 # TODO: Need to cause an exception on create but these tests
852 # aren't setup for mocking. Just create a record now so the
853 # second one is a dupicate
854 parent = TimeEntryActivity.find(9)
855 TimeEntryActivity.create!({:name => parent.name, :project_id => 1, :position => parent.position, :active => true})
856 TimeEntry.create!({:project_id => 1, :hours => 1.0, :user => User.find(1), :issue_id => 3, :activity_id => 10, :spent_on => '2009-01-01'})
858 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size
859 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size
861 @request.session[:user_id] = 2 # manager
862 post :save_activities, :id => 1, :enumerations => {
863 "9"=> {"parent_id"=>"9", "custom_field_values"=>{"7" => "1"}, "active"=>"0"}, # Design
864 "10"=> {"parent_id"=>"10", "custom_field_values"=>{"7"=>"0"}, "active"=>"1"} # Development, Change custom value
866 assert_response :redirect
868 # TimeEntries shouldn't have been reassigned on the failed record
869 assert_equal 3, TimeEntry.find_all_by_activity_id_and_project_id(9, 1).size, "Time Entries are not assigned to system activities"
870 # TimeEntries shouldn't have been reassigned on the saved record either
871 assert_equal 1, TimeEntry.find_all_by_activity_id_and_project_id(10, 1).size, "Time Entries are not assigned to system activities"
874 # A hook that is manually registered later
875 class ProjectBasedTemplate < Redmine::Hook::ViewListener
876 def view_layouts_base_html_head(context)
877 # Adds a project stylesheet
878 stylesheet_link_tag(context[:project].identifier) if context[:project]
881 # Don't use this hook now
882 Redmine::Hook.clear_listeners
884 def test_hook_response
885 Redmine::Hook.add_listener(ProjectBasedTemplate)
887 assert_tag :tag => 'link', :attributes => {:href => '/stylesheets/ecookbook.css'},
888 :parent => {:tag => 'head'}
890 Redmine::Hook.clear_listeners