comparison test/unit/issue_test.rb @ 1464:261b3d9a4903 redmine-2.4

Update to Redmine 2.4 branch rev 12663
author Chris Cannam
date Tue, 14 Jan 2014 14:37:42 +0000
parents 433d4f72a19b
children e248c7af89ec
comparison
equal deleted inserted replaced
1296:038ba2d95de8 1464:261b3d9a4903
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2012 Jean-Philippe Lang 2 # Copyright (C) 2006-2013 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.
33 33
34 def teardown 34 def teardown
35 User.current = nil 35 User.current = nil
36 end 36 end
37 37
38 def test_initialize
39 issue = Issue.new
40
41 assert_nil issue.project_id
42 assert_nil issue.tracker_id
43 assert_nil issue.author_id
44 assert_nil issue.assigned_to_id
45 assert_nil issue.category_id
46
47 assert_equal IssueStatus.default, issue.status
48 assert_equal IssuePriority.default, issue.priority
49 end
50
38 def test_create 51 def test_create
39 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3, 52 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
40 :status_id => 1, :priority => IssuePriority.all.first, 53 :status_id => 1, :priority => IssuePriority.all.first,
41 :subject => 'test_create', 54 :subject => 'test_create',
42 :description => 'IssueTest#test_create', :estimated_hours => '1:30') 55 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
75 def test_due_date_lesser_than_start_date_should_not_validate 88 def test_due_date_lesser_than_start_date_should_not_validate
76 set_language_if_valid 'en' 89 set_language_if_valid 'en'
77 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02') 90 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
78 assert !issue.valid? 91 assert !issue.valid?
79 assert_include 'Due date must be greater than start date', issue.errors.full_messages 92 assert_include 'Due date must be greater than start date', issue.errors.full_messages
93 end
94
95 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
96 issue = Issue.generate(:start_date => '2013-06-04')
97 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
98 assert !issue.valid?
99 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
100 end
101
102 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
103 issue = Issue.generate!(:start_date => '2013-06-04')
104 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
105 issue.start_date = '2013-06-07'
106 assert !issue.valid?
107 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
108 end
109
110 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
111 issue = Issue.generate!(:start_date => '2013-06-04')
112 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
113 assert issue.valid?
114 end
115
116 def test_estimated_hours_should_be_validated
117 set_language_if_valid 'en'
118 ['-2'].each do |invalid|
119 issue = Issue.new(:estimated_hours => invalid)
120 assert !issue.valid?
121 assert_include 'Estimated time is invalid', issue.errors.full_messages
122 end
80 end 123 end
81 124
82 def test_create_with_required_custom_field 125 def test_create_with_required_custom_field
83 set_language_if_valid 'en' 126 set_language_if_valid 'en'
84 field = IssueCustomField.find_by_name('Database') 127 field = IssueCustomField.find_by_name('Database')
222 assert_visibility_match user, issues 265 assert_visibility_match user, issues
223 end 266 end
224 267
225 def test_visible_scope_for_member 268 def test_visible_scope_for_member
226 user = User.find(9) 269 user = User.find(9)
227 # User should see issues of projects for which he has view_issues permissions only 270 # User should see issues of projects for which user has view_issues permissions only
228 Role.non_member.remove_permission!(:view_issues) 271 Role.non_member.remove_permission!(:view_issues)
229 Member.create!(:principal => user, :project_id => 3, :role_ids => [2]) 272 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
230 issues = Issue.visible(user).all 273 issues = Issue.visible(user).all
231 assert issues.any? 274 assert issues.any?
232 assert_nil issues.detect {|issue| issue.project_id != 3} 275 assert_nil issues.detect {|issue| issue.project_id != 3}
237 def test_visible_scope_for_member_with_groups_should_return_assigned_issues 280 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
238 user = User.find(8) 281 user = User.find(8)
239 assert user.groups.any? 282 assert user.groups.any?
240 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2]) 283 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
241 Role.non_member.remove_permission!(:view_issues) 284 Role.non_member.remove_permission!(:view_issues)
242 285
243 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, 286 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
244 :status_id => 1, :priority => IssuePriority.all.first, 287 :status_id => 1, :priority => IssuePriority.all.first,
245 :subject => 'Assignment test', 288 :subject => 'Assignment test',
246 :assigned_to => user.groups.first, 289 :assigned_to => user.groups.first,
247 :is_private => true) 290 :is_private => true)
248 291
249 Role.find(2).update_attribute :issues_visibility, 'default' 292 Role.find(2).update_attribute :issues_visibility, 'default'
250 issues = Issue.visible(User.find(8)).all 293 issues = Issue.visible(User.find(8)).all
251 assert issues.any? 294 assert issues.any?
252 assert issues.include?(issue) 295 assert issues.include?(issue)
253 296
254 Role.find(2).update_attribute :issues_visibility, 'own' 297 Role.find(2).update_attribute :issues_visibility, 'own'
255 issues = Issue.visible(User.find(8)).all 298 issues = Issue.visible(User.find(8)).all
256 assert issues.any? 299 assert issues.any?
257 assert issues.include?(issue) 300 assert issues.include?(issue)
258 end 301 end
261 user = User.find(1) 304 user = User.find(1)
262 user.members.each(&:destroy) 305 user.members.each(&:destroy)
263 assert user.projects.empty? 306 assert user.projects.empty?
264 issues = Issue.visible(user).all 307 issues = Issue.visible(user).all
265 assert issues.any? 308 assert issues.any?
266 # Admin should see issues on private projects that he does not belong to 309 # Admin should see issues on private projects that admin does not belong to
267 assert issues.detect {|issue| !issue.project.is_public?} 310 assert issues.detect {|issue| !issue.project.is_public?}
268 # Admin should see private issues of other users 311 # Admin should see private issues of other users
269 assert issues.detect {|issue| issue.is_private? && issue.author != user} 312 assert issues.detect {|issue| issue.is_private? && issue.author != user}
270 assert_visibility_match user, issues 313 assert_visibility_match user, issues
271 end 314 end
296 end 339 end
297 340
298 def test_open_scope_with_arg 341 def test_open_scope_with_arg
299 issues = Issue.open(false).all 342 issues = Issue.open(false).all
300 assert_equal issues, issues.select(&:closed?) 343 assert_equal issues, issues.select(&:closed?)
344 end
345
346 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
347 version = Version.find(2)
348 assert version.fixed_issues.any?
349 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
350 end
351
352 def test_fixed_version_scope_with_empty_array_should_return_no_result
353 assert_equal 0, Issue.fixed_version([]).count
301 end 354 end
302 355
303 def test_errors_full_messages_should_include_custom_fields_errors 356 def test_errors_full_messages_should_include_custom_fields_errors
304 field = IssueCustomField.find_by_name('Database') 357 field = IssueCustomField.find_by_name('Database')
305 358
400 issue = Issue.new(:project => Project.find(1)) 453 issue = Issue.new(:project => Project.find(1))
401 issue.attributes = attributes 454 issue.attributes = attributes
402 assert_equal 'MySQL', issue.custom_field_value(1) 455 assert_equal 'MySQL', issue.custom_field_value(1)
403 end 456 end
404 457
458 def test_reload_should_reload_custom_field_values
459 issue = Issue.generate!
460 issue.custom_field_values = {'2' => 'Foo'}
461 issue.save!
462
463 issue = Issue.order('id desc').first
464 assert_equal 'Foo', issue.custom_field_value(2)
465
466 issue.custom_field_values = {'2' => 'Bar'}
467 assert_equal 'Bar', issue.custom_field_value(2)
468
469 issue.reload
470 assert_equal 'Foo', issue.custom_field_value(2)
471 end
472
405 def test_should_update_issue_with_disabled_tracker 473 def test_should_update_issue_with_disabled_tracker
406 p = Project.find(1) 474 p = Project.find(1)
407 issue = Issue.find(1) 475 issue = Issue.find(1)
408 476
409 p.trackers.delete(issue.tracker) 477 p.trackers.delete(issue.tracker)
420 488
421 issue = Issue.find(1) 489 issue = Issue.find(1)
422 issue.tracker_id = 2 490 issue.tracker_id = 2
423 issue.subject = 'New subject' 491 issue.subject = 'New subject'
424 assert !issue.save 492 assert !issue.save
425 assert_not_nil issue.errors[:tracker_id] 493 assert_not_equal [], issue.errors[:tracker_id]
426 end 494 end
427 495
428 def test_category_based_assignment 496 def test_category_based_assignment
429 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3, 497 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
430 :status_id => 1, :priority => IssuePriority.all.first, 498 :status_id => 1, :priority => IssuePriority.all.first,
439 :old_status_id => 1, :new_status_id => 2, 507 :old_status_id => 1, :new_status_id => 2,
440 :author => false, :assignee => false) 508 :author => false, :assignee => false)
441 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, 509 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
442 :old_status_id => 1, :new_status_id => 3, 510 :old_status_id => 1, :new_status_id => 3,
443 :author => true, :assignee => false) 511 :author => true, :assignee => false)
444 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, 512 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
445 :new_status_id => 4, :author => false, 513 :old_status_id => 1, :new_status_id => 4,
446 :assignee => true) 514 :author => false, :assignee => true)
447 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, 515 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
448 :old_status_id => 1, :new_status_id => 5, 516 :old_status_id => 1, :new_status_id => 5,
449 :author => true, :assignee => true) 517 :author => true, :assignee => true)
450 status = IssueStatus.find(1) 518 status = IssueStatus.find(1)
451 role = Role.find(1) 519 role = Role.find(1)
467 535
468 issue = Issue.generate!(:tracker => tracker, :status => status, 536 issue = Issue.generate!(:tracker => tracker, :status => status,
469 :project_id => 1, :author => user, 537 :project_id => 1, :author => user,
470 :assigned_to => user) 538 :assigned_to => user)
471 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id) 539 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
540
541 group = Group.generate!
542 group.users << user
543 issue = Issue.generate!(:tracker => tracker, :status => status,
544 :project_id => 1, :author => user,
545 :assigned_to => group)
546 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
547 end
548
549 def test_new_statuses_allowed_to_should_consider_group_assignment
550 WorkflowTransition.delete_all
551 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
552 :old_status_id => 1, :new_status_id => 4,
553 :author => false, :assignee => true)
554 user = User.find(2)
555 group = Group.generate!
556 group.users << user
557
558 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
559 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
472 end 560 end
473 561
474 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin 562 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
475 admin = User.find(1) 563 admin = User.find(1)
476 issue = Issue.find(1) 564 issue = Issue.find(1)
477 assert !admin.member_of?(issue.project) 565 assert !admin.member_of?(issue.project)
478 expected_statuses = [issue.status] + 566 expected_statuses = [issue.status] +
479 WorkflowTransition.find_all_by_old_status_id( 567 WorkflowTransition.find_all_by_old_status_id(
480 issue.status_id).map(&:new_status).uniq.sort 568 issue.status_id).map(&:new_status).uniq.sort
481 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin) 569 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
482 end 570 end
483 571
800 child_copy = copy.children.detect {|c| c.subject == 'Child1'} 888 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
801 assert_equal %w(Child11), child_copy.children.map(&:subject).sort 889 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
802 assert_equal copy.author, child_copy.author 890 assert_equal copy.author, child_copy.author
803 end 891 end
804 892
893 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
894 parent = Issue.generate!
895 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
896 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
897
898 copy = parent.reload.copy
899 copy.parent_issue_id = parent.id
900 copy.author = User.find(7)
901 assert_difference 'Issue.count', 3 do
902 assert copy.save
903 end
904 parent.reload
905 copy.reload
906 assert_equal parent, copy.parent
907 assert_equal 3, parent.children.count
908 assert_equal 5, parent.descendants.count
909 assert_equal 2, copy.children.count
910 assert_equal 2, copy.descendants.count
911 end
912
913 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
914 parent = Issue.generate!
915 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
916 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
917
918 copy = parent.reload.copy
919 copy.parent_issue_id = child1.id
920 copy.author = User.find(7)
921 assert_difference 'Issue.count', 3 do
922 assert copy.save
923 end
924 parent.reload
925 child1.reload
926 copy.reload
927 assert_equal child1, copy.parent
928 assert_equal 2, parent.children.count
929 assert_equal 5, parent.descendants.count
930 assert_equal 1, child1.children.count
931 assert_equal 3, child1.descendants.count
932 assert_equal 2, copy.children.count
933 assert_equal 2, copy.descendants.count
934 end
935
805 def test_copy_should_copy_subtasks_to_target_project 936 def test_copy_should_copy_subtasks_to_target_project
806 issue = Issue.generate_with_descendants! 937 issue = Issue.generate_with_descendants!
807 938
808 copy = issue.copy(:project_id => 3) 939 copy = issue.copy(:project_id => 3)
809 assert_difference 'Issue.count', 1+issue.descendants.count do 940 assert_difference 'Issue.count', 1+issue.descendants.count do
874 :relation_type => IssueRelation::TYPE_DUPLICATES) 1005 :relation_type => IssueRelation::TYPE_DUPLICATES)
875 1006
876 assert issue1.reload.duplicates.include?(issue2) 1007 assert issue1.reload.duplicates.include?(issue2)
877 1008
878 # Closing issue 1 1009 # Closing issue 1
879 issue1.init_journal(User.find(:first), "Closing issue1") 1010 issue1.init_journal(User.first, "Closing issue1")
880 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true} 1011 issue1.status = IssueStatus.where(:is_closed => true).first
881 assert issue1.save 1012 assert issue1.save
882 # 2 and 3 should be also closed 1013 # 2 and 3 should be also closed
883 assert issue2.reload.closed? 1014 assert issue2.reload.closed?
884 assert issue3.reload.closed? 1015 assert issue3.reload.closed?
885 end 1016 end
893 :relation_type => IssueRelation::TYPE_DUPLICATES) 1024 :relation_type => IssueRelation::TYPE_DUPLICATES)
894 # 2 is a dup of 1 but 1 is not a duplicate of 2 1025 # 2 is a dup of 1 but 1 is not a duplicate of 2
895 assert !issue2.reload.duplicates.include?(issue1) 1026 assert !issue2.reload.duplicates.include?(issue1)
896 1027
897 # Closing issue 2 1028 # Closing issue 2
898 issue2.init_journal(User.find(:first), "Closing issue2") 1029 issue2.init_journal(User.first, "Closing issue2")
899 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true} 1030 issue2.status = IssueStatus.where(:is_closed => true).first
900 assert issue2.save 1031 assert issue2.save
901 # 1 should not be also closed 1032 # 1 should not be also closed
902 assert !issue1.reload.closed? 1033 assert !issue1.reload.closed?
903 end 1034 end
904 1035
912 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version 1043 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
913 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, 1044 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
914 :status_id => 1, :fixed_version_id => 1, 1045 :status_id => 1, :fixed_version_id => 1,
915 :subject => 'New issue') 1046 :subject => 'New issue')
916 assert !issue.save 1047 assert !issue.save
917 assert_not_nil issue.errors[:fixed_version_id] 1048 assert_not_equal [], issue.errors[:fixed_version_id]
918 end 1049 end
919 1050
920 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version 1051 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
921 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, 1052 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
922 :status_id => 1, :fixed_version_id => 2, 1053 :status_id => 1, :fixed_version_id => 2,
923 :subject => 'New issue') 1054 :subject => 'New issue')
924 assert !issue.save 1055 assert !issue.save
925 assert_not_nil issue.errors[:fixed_version_id] 1056 assert_not_equal [], issue.errors[:fixed_version_id]
926 end 1057 end
927 1058
928 def test_should_be_able_to_assign_a_new_issue_to_an_open_version 1059 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
929 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, 1060 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
930 :status_id => 1, :fixed_version_id => 3, 1061 :status_id => 1, :fixed_version_id => 3,
941 1072
942 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version 1073 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
943 issue = Issue.find(11) 1074 issue = Issue.find(11)
944 issue.status_id = 1 1075 issue.status_id = 1
945 assert !issue.save 1076 assert !issue.save
946 assert_not_nil issue.errors[:base] 1077 assert_not_equal [], issue.errors[:base]
947 end 1078 end
948 1079
949 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version 1080 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
950 issue = Issue.find(11) 1081 issue = Issue.find(11)
951 issue.status_id = 1 1082 issue.status_id = 1
970 assert_include 'Target version is not included in the list', issue.errors.full_messages 1101 assert_include 'Target version is not included in the list', issue.errors.full_messages
971 end 1102 end
972 1103
973 def test_should_keep_shared_version_when_changing_project 1104 def test_should_keep_shared_version_when_changing_project
974 Version.find(2).update_attribute :sharing, 'tree' 1105 Version.find(2).update_attribute :sharing, 'tree'
975 1106
976 issue = Issue.find(2) 1107 issue = Issue.find(2)
977 assert_equal 2, issue.fixed_version_id 1108 assert_equal 2, issue.fixed_version_id
978 issue.project_id = 3 1109 issue.project_id = 3
979 assert_equal 2, issue.fixed_version_id 1110 assert_equal 2, issue.fixed_version_id
980 assert issue.save 1111 assert issue.save
1108 assert_equal Tracker.find(2), copy.tracker 1239 assert_equal Tracker.find(2), copy.tracker
1109 # Custom field #2 is not associated with target tracker 1240 # Custom field #2 is not associated with target tracker
1110 assert_nil copy.custom_value_for(2) 1241 assert_nil copy.custom_value_for(2)
1111 end 1242 end
1112 1243
1113 context "#copy" do 1244 test "#copy should not create a journal" do
1114 setup do 1245 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1115 @issue = Issue.find(1) 1246 copy.save!
1116 end 1247 assert_equal 0, copy.reload.journals.size
1117 1248 end
1118 should "not create a journal" do 1249
1119 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3) 1250 test "#copy should allow assigned_to changes" do
1120 copy.save! 1251 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
1121 assert_equal 0, copy.reload.journals.size 1252 assert_equal 3, copy.assigned_to_id
1122 end 1253 end
1123 1254
1124 should "allow assigned_to changes" do 1255 test "#copy should allow status changes" do
1125 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3) 1256 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
1126 assert_equal 3, copy.assigned_to_id 1257 assert_equal 2, copy.status_id
1127 end 1258 end
1128 1259
1129 should "allow status changes" do 1260 test "#copy should allow start date changes" do
1130 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :status_id => 2) 1261 date = Date.today
1131 assert_equal 2, copy.status_id 1262 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1132 end 1263 assert_equal date, copy.start_date
1133 1264 end
1134 should "allow start date changes" do 1265
1135 date = Date.today 1266 test "#copy should allow due date changes" do
1136 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date) 1267 date = Date.today
1137 assert_equal date, copy.start_date 1268 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
1138 end 1269 assert_equal date, copy.due_date
1139 1270 end
1140 should "allow due date changes" do 1271
1141 date = Date.today 1272 test "#copy should set current user as author" do
1142 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :due_date => date) 1273 User.current = User.find(9)
1143 assert_equal date, copy.due_date 1274 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
1144 end 1275 assert_equal User.current, copy.author
1145 1276 end
1146 should "set current user as author" do 1277
1147 User.current = User.find(9) 1278 test "#copy should create a journal with notes" do
1148 copy = @issue.copy(:project_id => 3, :tracker_id => 2) 1279 date = Date.today
1149 assert_equal User.current, copy.author 1280 notes = "Notes added when copying"
1150 end 1281 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
1151 1282 copy.init_journal(User.current, notes)
1152 should "create a journal with notes" do 1283 copy.save!
1153 date = Date.today 1284
1154 notes = "Notes added when copying" 1285 assert_equal 1, copy.journals.size
1155 copy = @issue.copy(:project_id => 3, :tracker_id => 2, :start_date => date) 1286 journal = copy.journals.first
1156 copy.init_journal(User.current, notes) 1287 assert_equal 0, journal.details.size
1157 copy.save! 1288 assert_equal notes, journal.notes
1158
1159 assert_equal 1, copy.journals.size
1160 journal = copy.journals.first
1161 assert_equal 0, journal.details.size
1162 assert_equal notes, journal.notes
1163 end
1164 end 1289 end
1165 1290
1166 def test_valid_parent_project 1291 def test_valid_parent_project
1167 issue = Issue.find(1) 1292 issue = Issue.find(1)
1168 issue_in_same_project = Issue.find(2) 1293 issue_in_same_project = Issue.find(2)
1368 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') 1493 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1369 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, 1494 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1370 :relation_type => IssueRelation::TYPE_PRECEDES) 1495 :relation_type => IssueRelation::TYPE_PRECEDES)
1371 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date 1496 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1372 1497
1498 issue1.reload
1373 issue1.due_date = '2012-10-23' 1499 issue1.due_date = '2012-10-23'
1374 issue1.save! 1500 issue1.save!
1375 issue2.reload 1501 issue2.reload
1376 assert_equal Date.parse('2012-10-24'), issue2.start_date 1502 assert_equal Date.parse('2012-10-24'), issue2.start_date
1377 assert_equal Date.parse('2012-10-26'), issue2.due_date 1503 assert_equal Date.parse('2012-10-26'), issue2.due_date
1382 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17') 1508 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1383 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, 1509 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1384 :relation_type => IssueRelation::TYPE_PRECEDES) 1510 :relation_type => IssueRelation::TYPE_PRECEDES)
1385 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date 1511 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1386 1512
1513 issue1.reload
1387 issue1.start_date = '2012-09-17' 1514 issue1.start_date = '2012-09-17'
1388 issue1.due_date = '2012-09-18' 1515 issue1.due_date = '2012-09-18'
1389 issue1.save! 1516 issue1.save!
1390 issue2.reload 1517 issue2.reload
1391 assert_equal Date.parse('2012-09-19'), issue2.start_date 1518 assert_equal Date.parse('2012-09-19'), issue2.start_date
1400 :relation_type => IssueRelation::TYPE_PRECEDES) 1527 :relation_type => IssueRelation::TYPE_PRECEDES)
1401 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2, 1528 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
1402 :relation_type => IssueRelation::TYPE_PRECEDES) 1529 :relation_type => IssueRelation::TYPE_PRECEDES)
1403 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date 1530 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
1404 1531
1532 issue1.reload
1405 issue1.start_date = '2012-09-17' 1533 issue1.start_date = '2012-09-17'
1406 issue1.due_date = '2012-09-18' 1534 issue1.due_date = '2012-09-18'
1407 issue1.save! 1535 issue1.save!
1408 issue2.reload 1536 issue2.reload
1409 # Issue 2 must start after Issue 3 1537 # Issue 2 must start after Issue 3
1423 end 1551 end
1424 assert_equal date, stale.reload.start_date 1552 assert_equal date, stale.reload.start_date
1425 end 1553 end
1426 end 1554 end
1427 1555
1556 def test_child_issue_should_consider_parent_soonest_start_on_create
1557 set_language_if_valid 'en'
1558 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
1559 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
1560 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
1561 :relation_type => IssueRelation::TYPE_PRECEDES)
1562 issue1.reload
1563 issue2.reload
1564 assert_equal Date.parse('2012-10-18'), issue2.start_date
1565
1566 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
1567 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
1568 assert !child.valid?
1569 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
1570 assert_equal Date.parse('2012-10-18'), child.soonest_start
1571 child.start_date = '2012-10-18'
1572 assert child.save
1573 end
1574
1575 def test_setting_parent_to_a_dependent_issue_should_not_validate
1576 set_language_if_valid 'en'
1577 issue1 = Issue.generate!
1578 issue2 = Issue.generate!
1579 issue3 = Issue.generate!
1580 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1581 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
1582 issue3.reload
1583 issue3.parent_issue_id = issue2.id
1584 assert !issue3.valid?
1585 assert_include 'Parent task is invalid', issue3.errors.full_messages
1586 end
1587
1588 def test_setting_parent_should_not_allow_circular_dependency
1589 set_language_if_valid 'en'
1590 issue1 = Issue.generate!
1591 issue2 = Issue.generate!
1592 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
1593 issue3 = Issue.generate!
1594 issue2.reload
1595 issue2.parent_issue_id = issue3.id
1596 issue2.save!
1597 issue4 = Issue.generate!
1598 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
1599 issue4.reload
1600 issue4.parent_issue_id = issue1.id
1601 assert !issue4.valid?
1602 assert_include 'Parent task is invalid', issue4.errors.full_messages
1603 end
1604
1428 def test_overdue 1605 def test_overdue
1429 assert Issue.new(:due_date => 1.day.ago.to_date).overdue? 1606 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
1430 assert !Issue.new(:due_date => Date.today).overdue? 1607 assert !Issue.new(:due_date => Date.today).overdue?
1431 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue? 1608 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
1432 assert !Issue.new(:due_date => nil).overdue? 1609 assert !Issue.new(:due_date => nil).overdue?
1433 assert !Issue.new(:due_date => 1.day.ago.to_date, 1610 assert !Issue.new(:due_date => 1.day.ago.to_date,
1434 :status => IssueStatus.find(:first, 1611 :status => IssueStatus.where(:is_closed => true).first
1435 :conditions => {:is_closed => true})
1436 ).overdue? 1612 ).overdue?
1437 end 1613 end
1438 1614
1439 context "#behind_schedule?" do 1615 test "#behind_schedule? should be false if the issue has no start_date" do
1440 should "be false if the issue has no start_date" do 1616 assert !Issue.new(:start_date => nil,
1441 assert !Issue.new(:start_date => nil, 1617 :due_date => 1.day.from_now.to_date,
1442 :due_date => 1.day.from_now.to_date, 1618 :done_ratio => 0).behind_schedule?
1443 :done_ratio => 0).behind_schedule? 1619 end
1444 end 1620
1445 1621 test "#behind_schedule? should be false if the issue has no end_date" do
1446 should "be false if the issue has no end_date" do 1622 assert !Issue.new(:start_date => 1.day.from_now.to_date,
1447 assert !Issue.new(:start_date => 1.day.from_now.to_date, 1623 :due_date => nil,
1448 :due_date => nil, 1624 :done_ratio => 0).behind_schedule?
1449 :done_ratio => 0).behind_schedule? 1625 end
1450 end 1626
1451 1627 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
1452 should "be false if the issue has more done than it's calendar time" do 1628 assert !Issue.new(:start_date => 50.days.ago.to_date,
1453 assert !Issue.new(:start_date => 50.days.ago.to_date, 1629 :due_date => 50.days.from_now.to_date,
1454 :due_date => 50.days.from_now.to_date, 1630 :done_ratio => 90).behind_schedule?
1455 :done_ratio => 90).behind_schedule? 1631 end
1456 end 1632
1457 1633 test "#behind_schedule? should be true if the issue hasn't been started at all" do
1458 should "be true if the issue hasn't been started at all" do 1634 assert Issue.new(:start_date => 1.day.ago.to_date,
1459 assert Issue.new(:start_date => 1.day.ago.to_date, 1635 :due_date => 1.day.from_now.to_date,
1460 :due_date => 1.day.from_now.to_date, 1636 :done_ratio => 0).behind_schedule?
1461 :done_ratio => 0).behind_schedule? 1637 end
1462 end 1638
1463 1639 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
1464 should "be true if the issue has used more calendar time than it's done ratio" do 1640 assert Issue.new(:start_date => 100.days.ago.to_date,
1465 assert Issue.new(:start_date => 100.days.ago.to_date, 1641 :due_date => Date.today,
1466 :due_date => Date.today, 1642 :done_ratio => 90).behind_schedule?
1467 :done_ratio => 90).behind_schedule? 1643 end
1468 end 1644
1469 end 1645 test "#assignable_users should be Users" do
1470 1646 assert_kind_of User, Issue.find(1).assignable_users.first
1471 context "#assignable_users" do 1647 end
1472 should "be Users" do 1648
1473 assert_kind_of User, Issue.find(1).assignable_users.first 1649 test "#assignable_users should include the issue author" do
1474 end 1650 non_project_member = User.generate!
1475 1651 issue = Issue.generate!(:author => non_project_member)
1476 should "include the issue author" do 1652
1477 non_project_member = User.generate! 1653 assert issue.assignable_users.include?(non_project_member)
1478 issue = Issue.generate!(:author => non_project_member) 1654 end
1479 1655
1480 assert issue.assignable_users.include?(non_project_member) 1656 test "#assignable_users should include the current assignee" do
1481 end 1657 user = User.generate!
1482 1658 issue = Issue.generate!(:assigned_to => user)
1483 should "include the current assignee" do 1659 user.lock!
1484 user = User.generate! 1660
1485 issue = Issue.generate!(:assigned_to => user) 1661 assert Issue.find(issue.id).assignable_users.include?(user)
1486 user.lock! 1662 end
1487 1663
1488 assert Issue.find(issue.id).assignable_users.include?(user) 1664 test "#assignable_users should not show the issue author twice" do
1489 end 1665 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
1490 1666 assert_equal 2, assignable_user_ids.length
1491 should "not show the issue author twice" do 1667
1492 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id) 1668 assignable_user_ids.each do |user_id|
1493 assert_equal 2, assignable_user_ids.length 1669 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
1494 1670 "User #{user_id} appears more or less than once"
1495 assignable_user_ids.each do |user_id| 1671 end
1496 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, 1672 end
1497 "User #{user_id} appears more or less than once" 1673
1498 end 1674 test "#assignable_users with issue_group_assignment should include groups" do
1499 end 1675 issue = Issue.new(:project => Project.find(2))
1500 1676
1501 context "with issue_group_assignment" do 1677 with_settings :issue_group_assignment => '1' do
1502 should "include groups" do 1678 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1503 issue = Issue.new(:project => Project.find(2)) 1679 assert issue.assignable_users.include?(Group.find(11))
1504 1680 end
1505 with_settings :issue_group_assignment => '1' do 1681 end
1506 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort 1682
1507 assert issue.assignable_users.include?(Group.find(11)) 1683 test "#assignable_users without issue_group_assignment should not include groups" do
1508 end 1684 issue = Issue.new(:project => Project.find(2))
1509 end 1685
1510 end 1686 with_settings :issue_group_assignment => '0' do
1511 1687 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1512 context "without issue_group_assignment" do 1688 assert !issue.assignable_users.include?(Group.find(11))
1513 should "not include groups" do
1514 issue = Issue.new(:project => Project.find(2))
1515
1516 with_settings :issue_group_assignment => '0' do
1517 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
1518 assert !issue.assignable_users.include?(Group.find(11))
1519 end
1520 end
1521 end 1689 end
1522 end 1690 end
1523 1691
1524 def test_create_should_send_email_notification 1692 def test_create_should_send_email_notification
1525 ActionMailer::Base.deliveries.clear 1693 ActionMailer::Base.deliveries.clear
1528 :priority => IssuePriority.all.first, 1696 :priority => IssuePriority.all.first,
1529 :subject => 'test_create', :estimated_hours => '1:30') 1697 :subject => 'test_create', :estimated_hours => '1:30')
1530 1698
1531 assert issue.save 1699 assert issue.save
1532 assert_equal 1, ActionMailer::Base.deliveries.size 1700 assert_equal 1, ActionMailer::Base.deliveries.size
1701 end
1702
1703 def test_update_should_notify_previous_assignee
1704 ActionMailer::Base.deliveries.clear
1705 user = User.find(3)
1706 user.members.update_all ["mail_notification = ?", false]
1707 user.update_attribute :mail_notification, 'only_assigned'
1708
1709 issue = Issue.find(2)
1710 issue.init_journal User.find(1)
1711 issue.assigned_to = nil
1712 issue.save!
1713 assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
1533 end 1714 end
1534 1715
1535 def test_stale_issue_should_not_send_email_notification 1716 def test_stale_issue_should_not_send_email_notification
1536 ActionMailer::Base.deliveries.clear 1717 ActionMailer::Base.deliveries.clear
1537 issue = Issue.find(1) 1718 issue = Issue.find(1)
1628 i = Issue.new(:description => "CR \r LF \n CRLF \r\n") 1809 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
1629 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description 1810 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
1630 end 1811 end
1631 1812
1632 def test_saving_twice_should_not_duplicate_journal_details 1813 def test_saving_twice_should_not_duplicate_journal_details
1633 i = Issue.find(:first) 1814 i = Issue.first
1634 i.init_journal(User.find(2), 'Some notes') 1815 i.init_journal(User.find(2), 'Some notes')
1635 # initial changes 1816 # initial changes
1636 i.subject = 'New subject' 1817 i.subject = 'New subject'
1637 i.done_ratio = i.done_ratio + 10 1818 i.done_ratio = i.done_ratio + 10
1638 assert_difference 'Journal.count' do 1819 assert_difference 'Journal.count' do
1639 assert i.save 1820 assert i.save
1640 end 1821 end
1641 # 1 more change 1822 # 1 more change
1642 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id]) 1823 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
1643 assert_no_difference 'Journal.count' do 1824 assert_no_difference 'Journal.count' do
1644 assert_difference 'JournalDetail.count', 1 do 1825 assert_difference 'JournalDetail.count', 1 do
1645 i.save 1826 i.save
1646 end 1827 end
1647 end 1828 end
1666 :relation_type => IssueRelation::TYPE_PRECEDES) 1847 :relation_type => IssueRelation::TYPE_PRECEDES)
1667 1848
1668 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort 1849 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1669 end 1850 end
1670 1851
1852 def test_all_dependent_issues_with_subtask
1853 IssueRelation.delete_all
1854
1855 project = Project.generate!(:name => "testproject")
1856
1857 parentIssue = Issue.generate!(:project => project)
1858 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1859 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1860
1861 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
1862 end
1863
1864 def test_all_dependent_issues_does_not_include_self
1865 IssueRelation.delete_all
1866
1867 project = Project.generate!(:name => "testproject")
1868
1869 parentIssue = Issue.generate!(:project => project)
1870 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1871
1872 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
1873 end
1874
1875 def test_all_dependent_issues_with_parenttask_and_sibling
1876 IssueRelation.delete_all
1877
1878 project = Project.generate!(:name => "testproject")
1879
1880 parentIssue = Issue.generate!(:project => project)
1881 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1882 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
1883
1884 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
1885 end
1886
1887 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
1888 IssueRelation.delete_all
1889
1890 project = Project.generate!(:name => "testproject")
1891
1892 parentIssue1 = Issue.generate!(:project => project)
1893 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1894 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1895
1896 parentIssue2 = Issue.generate!(:project => project)
1897 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1898 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1899
1900
1901 assert IssueRelation.create(:issue_from => parentIssue1,
1902 :issue_to => childIssue2_2,
1903 :relation_type => IssueRelation::TYPE_BLOCKS)
1904
1905 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
1906 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1907 end
1908
1909 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
1910 IssueRelation.delete_all
1911
1912 project = Project.generate!(:name => "testproject")
1913
1914 parentIssue1 = Issue.generate!(:project => project)
1915 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1916 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1917
1918 parentIssue2 = Issue.generate!(:project => project)
1919 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1920 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1921
1922
1923 assert IssueRelation.create(:issue_from => parentIssue1,
1924 :issue_to => parentIssue2,
1925 :relation_type => IssueRelation::TYPE_BLOCKS)
1926
1927 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
1928 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1929 end
1930
1931 def test_all_dependent_issues_with_transitive_relation
1932 IssueRelation.delete_all
1933
1934 project = Project.generate!(:name => "testproject")
1935
1936 parentIssue1 = Issue.generate!(:project => project)
1937 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1938
1939 parentIssue2 = Issue.generate!(:project => project)
1940 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1941
1942 independentIssue = Issue.generate!(:project => project)
1943
1944 assert IssueRelation.create(:issue_from => parentIssue1,
1945 :issue_to => childIssue2_1,
1946 :relation_type => IssueRelation::TYPE_RELATES)
1947
1948 assert IssueRelation.create(:issue_from => childIssue2_1,
1949 :issue_to => independentIssue,
1950 :relation_type => IssueRelation::TYPE_RELATES)
1951
1952 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1953 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1954 end
1955
1956 def test_all_dependent_issues_with_transitive_relation2
1957 IssueRelation.delete_all
1958
1959 project = Project.generate!(:name => "testproject")
1960
1961 parentIssue1 = Issue.generate!(:project => project)
1962 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
1963
1964 parentIssue2 = Issue.generate!(:project => project)
1965 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
1966
1967 independentIssue = Issue.generate!(:project => project)
1968
1969 assert IssueRelation.create(:issue_from => parentIssue1,
1970 :issue_to => independentIssue,
1971 :relation_type => IssueRelation::TYPE_RELATES)
1972
1973 assert IssueRelation.create(:issue_from => independentIssue,
1974 :issue_to => childIssue2_1,
1975 :relation_type => IssueRelation::TYPE_RELATES)
1976
1977 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
1978 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
1979
1980 end
1981
1671 def test_all_dependent_issues_with_persistent_circular_dependency 1982 def test_all_dependent_issues_with_persistent_circular_dependency
1672 IssueRelation.delete_all 1983 IssueRelation.delete_all
1673 assert IssueRelation.create!(:issue_from => Issue.find(1), 1984 assert IssueRelation.create!(:issue_from => Issue.find(1),
1674 :issue_to => Issue.find(2), 1985 :issue_to => Issue.find(2),
1675 :relation_type => IssueRelation::TYPE_PRECEDES) 1986 :relation_type => IssueRelation::TYPE_PRECEDES)
1679 1990
1680 r = IssueRelation.create!(:issue_from => Issue.find(3), 1991 r = IssueRelation.create!(:issue_from => Issue.find(3),
1681 :issue_to => Issue.find(7), 1992 :issue_to => Issue.find(7),
1682 :relation_type => IssueRelation::TYPE_PRECEDES) 1993 :relation_type => IssueRelation::TYPE_PRECEDES)
1683 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id]) 1994 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1684 1995
1685 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort 1996 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
1686 end 1997 end
1687 1998
1688 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies 1999 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
1689 IssueRelation.delete_all 2000 IssueRelation.delete_all
1699 2010
1700 r = IssueRelation.create!(:issue_from => Issue.find(8), 2011 r = IssueRelation.create!(:issue_from => Issue.find(8),
1701 :issue_to => Issue.find(7), 2012 :issue_to => Issue.find(7),
1702 :relation_type => IssueRelation::TYPE_RELATES) 2013 :relation_type => IssueRelation::TYPE_RELATES)
1703 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id]) 2014 IssueRelation.update_all("issue_to_id = 2", ["id = ?", r.id])
1704 2015
1705 r = IssueRelation.create!(:issue_from => Issue.find(3), 2016 r = IssueRelation.create!(:issue_from => Issue.find(3),
1706 :issue_to => Issue.find(7), 2017 :issue_to => Issue.find(7),
1707 :relation_type => IssueRelation::TYPE_RELATES) 2018 :relation_type => IssueRelation::TYPE_RELATES)
1708 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id]) 2019 IssueRelation.update_all("issue_to_id = 1", ["id = ?", r.id])
1709 2020
1710 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort 2021 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
1711 end 2022 end
1712 2023
1713 context "#done_ratio" do 2024 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
1714 setup do 2025 @issue = Issue.find(1)
1715 @issue = Issue.find(1) 2026 @issue_status = IssueStatus.find(1)
1716 @issue_status = IssueStatus.find(1) 2027 @issue_status.update_attribute(:default_done_ratio, 50)
1717 @issue_status.update_attribute(:default_done_ratio, 50) 2028 @issue2 = Issue.find(2)
1718 @issue2 = Issue.find(2) 2029 @issue_status2 = IssueStatus.find(2)
1719 @issue_status2 = IssueStatus.find(2) 2030 @issue_status2.update_attribute(:default_done_ratio, 0)
1720 @issue_status2.update_attribute(:default_done_ratio, 0) 2031
1721 end 2032 with_settings :issue_done_ratio => 'issue_field' do
1722 2033 assert_equal 0, @issue.done_ratio
1723 teardown do 2034 assert_equal 30, @issue2.done_ratio
1724 Setting.issue_done_ratio = 'issue_field' 2035 end
1725 end 2036
1726 2037 with_settings :issue_done_ratio => 'issue_status' do
1727 context "with Setting.issue_done_ratio using the issue_field" do 2038 assert_equal 50, @issue.done_ratio
1728 setup do 2039 assert_equal 0, @issue2.done_ratio
1729 Setting.issue_done_ratio = 'issue_field' 2040 end
1730 end 2041 end
1731 2042
1732 should "read the issue's field" do 2043 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
1733 assert_equal 0, @issue.done_ratio 2044 @issue = Issue.find(1)
1734 assert_equal 30, @issue2.done_ratio 2045 @issue_status = IssueStatus.find(1)
1735 end 2046 @issue_status.update_attribute(:default_done_ratio, 50)
1736 end 2047 @issue2 = Issue.find(2)
1737 2048 @issue_status2 = IssueStatus.find(2)
1738 context "with Setting.issue_done_ratio using the issue_status" do 2049 @issue_status2.update_attribute(:default_done_ratio, 0)
1739 setup do 2050
1740 Setting.issue_done_ratio = 'issue_status' 2051 with_settings :issue_done_ratio => 'issue_field' do
1741 end 2052 @issue.update_done_ratio_from_issue_status
1742 2053 @issue2.update_done_ratio_from_issue_status
1743 should "read the Issue Status's default done ratio" do 2054
1744 assert_equal 50, @issue.done_ratio 2055 assert_equal 0, @issue.read_attribute(:done_ratio)
1745 assert_equal 0, @issue2.done_ratio 2056 assert_equal 30, @issue2.read_attribute(:done_ratio)
1746 end 2057 end
1747 end 2058
1748 end 2059 with_settings :issue_done_ratio => 'issue_status' do
1749 2060 @issue.update_done_ratio_from_issue_status
1750 context "#update_done_ratio_from_issue_status" do 2061 @issue2.update_done_ratio_from_issue_status
1751 setup do 2062
1752 @issue = Issue.find(1) 2063 assert_equal 50, @issue.read_attribute(:done_ratio)
1753 @issue_status = IssueStatus.find(1) 2064 assert_equal 0, @issue2.read_attribute(:done_ratio)
1754 @issue_status.update_attribute(:default_done_ratio, 50)
1755 @issue2 = Issue.find(2)
1756 @issue_status2 = IssueStatus.find(2)
1757 @issue_status2.update_attribute(:default_done_ratio, 0)
1758 end
1759
1760 context "with Setting.issue_done_ratio using the issue_field" do
1761 setup do
1762 Setting.issue_done_ratio = 'issue_field'
1763 end
1764
1765 should "not change the issue" do
1766 @issue.update_done_ratio_from_issue_status
1767 @issue2.update_done_ratio_from_issue_status
1768
1769 assert_equal 0, @issue.read_attribute(:done_ratio)
1770 assert_equal 30, @issue2.read_attribute(:done_ratio)
1771 end
1772 end
1773
1774 context "with Setting.issue_done_ratio using the issue_status" do
1775 setup do
1776 Setting.issue_done_ratio = 'issue_status'
1777 end
1778
1779 should "change the issue's done ratio" do
1780 @issue.update_done_ratio_from_issue_status
1781 @issue2.update_done_ratio_from_issue_status
1782
1783 assert_equal 50, @issue.read_attribute(:done_ratio)
1784 assert_equal 0, @issue2.read_attribute(:done_ratio)
1785 end
1786 end 2065 end
1787 end 2066 end
1788 2067
1789 test "#by_tracker" do 2068 test "#by_tracker" do
1790 User.current = User.anonymous 2069 User.current = User.anonymous
1791 groups = Issue.by_tracker(Project.find(1)) 2070 groups = Issue.by_tracker(Project.find(1))
1792 assert_equal 3, groups.size 2071 assert_equal 3, groups.count
1793 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2072 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1794 end 2073 end
1795 2074
1796 test "#by_version" do 2075 test "#by_version" do
1797 User.current = User.anonymous 2076 User.current = User.anonymous
1798 groups = Issue.by_version(Project.find(1)) 2077 groups = Issue.by_version(Project.find(1))
1799 assert_equal 3, groups.size 2078 assert_equal 3, groups.count
1800 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2079 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1801 end 2080 end
1802 2081
1803 test "#by_priority" do 2082 test "#by_priority" do
1804 User.current = User.anonymous 2083 User.current = User.anonymous
1805 groups = Issue.by_priority(Project.find(1)) 2084 groups = Issue.by_priority(Project.find(1))
1806 assert_equal 4, groups.size 2085 assert_equal 4, groups.count
1807 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2086 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1808 end 2087 end
1809 2088
1810 test "#by_category" do 2089 test "#by_category" do
1811 User.current = User.anonymous 2090 User.current = User.anonymous
1812 groups = Issue.by_category(Project.find(1)) 2091 groups = Issue.by_category(Project.find(1))
1813 assert_equal 2, groups.size 2092 assert_equal 2, groups.count
1814 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2093 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1815 end 2094 end
1816 2095
1817 test "#by_assigned_to" do 2096 test "#by_assigned_to" do
1818 User.current = User.anonymous 2097 User.current = User.anonymous
1819 groups = Issue.by_assigned_to(Project.find(1)) 2098 groups = Issue.by_assigned_to(Project.find(1))
1820 assert_equal 2, groups.size 2099 assert_equal 2, groups.count
1821 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2100 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1822 end 2101 end
1823 2102
1824 test "#by_author" do 2103 test "#by_author" do
1825 User.current = User.anonymous 2104 User.current = User.anonymous
1826 groups = Issue.by_author(Project.find(1)) 2105 groups = Issue.by_author(Project.find(1))
1827 assert_equal 4, groups.size 2106 assert_equal 4, groups.count
1828 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2107 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1829 end 2108 end
1830 2109
1831 test "#by_subproject" do 2110 test "#by_subproject" do
1832 User.current = User.anonymous 2111 User.current = User.anonymous
1833 groups = Issue.by_subproject(Project.find(1)) 2112 groups = Issue.by_subproject(Project.find(1))
1834 # Private descendant not visible 2113 # Private descendant not visible
1835 assert_equal 1, groups.size 2114 assert_equal 1, groups.count
1836 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i} 2115 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
1837 end 2116 end
1838 2117
1839 def test_recently_updated_scope 2118 def test_recently_updated_scope
1840 #should return the last updated issue 2119 #should return the last updated issue
1853 issue.project = Project.find(2) 2132 issue.project = Project.find(2)
1854 assert issue.save 2133 assert issue.save
1855 assert_equal before, Issue.on_active_project.length 2134 assert_equal before, Issue.on_active_project.length
1856 end 2135 end
1857 2136
1858 context "Issue#recipients" do 2137 test "Issue#recipients should include project recipients" do
1859 setup do 2138 issue = Issue.generate!
1860 @project = Project.find(1) 2139 assert issue.project.recipients.present?
1861 @author = User.generate! 2140 issue.project.recipients.each do |project_recipient|
1862 @assignee = User.generate! 2141 assert issue.recipients.include?(project_recipient)
1863 @issue = Issue.generate!(:project => @project, :assigned_to => @assignee, :author => @author) 2142 end
1864 end 2143 end
1865 2144
1866 should "include project recipients" do 2145 test "Issue#recipients should include the author if the author is active" do
1867 assert @project.recipients.present? 2146 issue = Issue.generate!(:author => User.generate!)
1868 @project.recipients.each do |project_recipient| 2147 assert issue.author, "No author set for Issue"
1869 assert @issue.recipients.include?(project_recipient) 2148 assert issue.recipients.include?(issue.author.mail)
1870 end 2149 end
1871 end 2150
1872 2151 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
1873 should "include the author if the author is active" do 2152 issue = Issue.generate!(:assigned_to => User.generate!)
1874 assert @issue.author, "No author set for Issue" 2153 assert issue.assigned_to, "No assigned_to set for Issue"
1875 assert @issue.recipients.include?(@issue.author.mail) 2154 assert issue.recipients.include?(issue.assigned_to.mail)
1876 end 2155 end
1877 2156
1878 should "include the assigned to user if the assigned to user is active" do 2157 test "Issue#recipients should not include users who opt out of all email" do
1879 assert @issue.assigned_to, "No assigned_to set for Issue" 2158 issue = Issue.generate!(:author => User.generate!)
1880 assert @issue.recipients.include?(@issue.assigned_to.mail) 2159 issue.author.update_attribute(:mail_notification, :none)
1881 end 2160 assert !issue.recipients.include?(issue.author.mail)
1882 2161 end
1883 should "not include users who opt out of all email" do 2162
1884 @author.update_attribute(:mail_notification, :none) 2163 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
1885 2164 issue = Issue.generate!(:author => User.generate!)
1886 assert !@issue.recipients.include?(@issue.author.mail) 2165 issue.author.update_attribute(:mail_notification, :only_assigned)
1887 end 2166 assert !issue.recipients.include?(issue.author.mail)
1888 2167 end
1889 should "not include the issue author if they are only notified of assigned issues" do 2168
1890 @author.update_attribute(:mail_notification, :only_assigned) 2169 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
1891 2170 issue = Issue.generate!(:assigned_to => User.generate!)
1892 assert !@issue.recipients.include?(@issue.author.mail) 2171 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
1893 end 2172 assert !issue.recipients.include?(issue.assigned_to.mail)
1894
1895 should "not include the assigned user if they are only notified of owned issues" do
1896 @assignee.update_attribute(:mail_notification, :only_owner)
1897
1898 assert !@issue.recipients.include?(@issue.assigned_to.mail)
1899 end
1900 end 2173 end
1901 2174
1902 def test_last_journal_id_with_journals_should_return_the_journal_id 2175 def test_last_journal_id_with_journals_should_return_the_journal_id
1903 assert_equal 2, Issue.find(1).last_journal_id 2176 assert_equal 2, Issue.find(1).last_journal_id
1904 end 2177 end
1912 assert_equal [], Issue.find(1).journals_after('2') 2185 assert_equal [], Issue.find(1).journals_after('2')
1913 end 2186 end
1914 2187
1915 def test_journals_after_with_blank_arg_should_return_all_journals 2188 def test_journals_after_with_blank_arg_should_return_all_journals
1916 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('') 2189 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
2190 end
2191
2192 def test_css_classes_should_include_tracker
2193 issue = Issue.new(:tracker => Tracker.find(2))
2194 classes = issue.css_classes.split(' ')
2195 assert_include 'tracker-2', classes
1917 end 2196 end
1918 2197
1919 def test_css_classes_should_include_priority 2198 def test_css_classes_should_include_priority
1920 issue = Issue.new(:priority => IssuePriority.find(8)) 2199 issue = Issue.new(:priority => IssuePriority.find(8))
1921 classes = issue.css_classes.split(' ') 2200 classes = issue.css_classes.split(' ')
1922 assert_include 'priority-8', classes 2201 assert_include 'priority-8', classes
1923 assert_include 'priority-highest', classes 2202 assert_include 'priority-highest', classes
2203 end
2204
2205 def test_css_classes_should_include_user_assignment
2206 issue = Issue.generate(:assigned_to_id => 2)
2207 assert_include 'assigned-to-me', issue.css_classes(User.find(2))
2208 assert_not_include 'assigned-to-me', issue.css_classes(User.find(3))
2209 end
2210
2211 def test_css_classes_should_include_user_group_assignment
2212 issue = Issue.generate(:assigned_to_id => 10)
2213 assert_include 'assigned-to-my-group', issue.css_classes(Group.find(10).users.first)
2214 assert_not_include 'assigned-to-my-group', issue.css_classes(User.find(3))
1924 end 2215 end
1925 2216
1926 def test_save_attachments_with_hash_should_save_attachments_in_keys_order 2217 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
1927 set_tmp_attachments_directory 2218 set_tmp_attachments_directory
1928 issue = Issue.generate! 2219 issue = Issue.generate!
1934 issue.attach_saved_attachments 2225 issue.attach_saved_attachments
1935 2226
1936 assert_equal 3, issue.reload.attachments.count 2227 assert_equal 3, issue.reload.attachments.count
1937 assert_equal %w(upload foo bar), issue.attachments.map(&:filename) 2228 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
1938 end 2229 end
2230
2231 def test_closed_on_should_be_nil_when_creating_an_open_issue
2232 issue = Issue.generate!(:status_id => 1).reload
2233 assert !issue.closed?
2234 assert_nil issue.closed_on
2235 end
2236
2237 def test_closed_on_should_be_set_when_creating_a_closed_issue
2238 issue = Issue.generate!(:status_id => 5).reload
2239 assert issue.closed?
2240 assert_not_nil issue.closed_on
2241 assert_equal issue.updated_on, issue.closed_on
2242 assert_equal issue.created_on, issue.closed_on
2243 end
2244
2245 def test_closed_on_should_be_nil_when_updating_an_open_issue
2246 issue = Issue.find(1)
2247 issue.subject = 'Not closed yet'
2248 issue.save!
2249 issue.reload
2250 assert_nil issue.closed_on
2251 end
2252
2253 def test_closed_on_should_be_set_when_closing_an_open_issue
2254 issue = Issue.find(1)
2255 issue.subject = 'Now closed'
2256 issue.status_id = 5
2257 issue.save!
2258 issue.reload
2259 assert_not_nil issue.closed_on
2260 assert_equal issue.updated_on, issue.closed_on
2261 end
2262
2263 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
2264 issue = Issue.open(false).first
2265 was_closed_on = issue.closed_on
2266 assert_not_nil was_closed_on
2267 issue.subject = 'Updating a closed issue'
2268 issue.save!
2269 issue.reload
2270 assert_equal was_closed_on, issue.closed_on
2271 end
2272
2273 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
2274 issue = Issue.open(false).first
2275 was_closed_on = issue.closed_on
2276 assert_not_nil was_closed_on
2277 issue.subject = 'Reopening a closed issue'
2278 issue.status_id = 1
2279 issue.save!
2280 issue.reload
2281 assert !issue.closed?
2282 assert_equal was_closed_on, issue.closed_on
2283 end
2284
2285 def test_status_was_should_return_nil_for_new_issue
2286 issue = Issue.new
2287 assert_nil issue.status_was
2288 end
2289
2290 def test_status_was_should_return_status_before_change
2291 issue = Issue.find(1)
2292 issue.status = IssueStatus.find(2)
2293 assert_equal IssueStatus.find(1), issue.status_was
2294 end
2295
2296 def test_status_was_should_be_reset_on_save
2297 issue = Issue.find(1)
2298 issue.status = IssueStatus.find(2)
2299 assert_equal IssueStatus.find(1), issue.status_was
2300 assert issue.save!
2301 assert_equal IssueStatus.find(2), issue.status_was
2302 end
1939 end 2303 end