annotate .svn/pristine/72/727874d7bc35b744eb4b647417de27d95212b4b8.svn-base @ 1524:82fac3dcf466 redmine-2.5-integration

Fix failure to interpret Javascript when autocompleting members for project
author Chris Cannam <chris.cannam@soundsoftware.ac.uk>
date Thu, 11 Sep 2014 10:24:38 +0100
parents cbb26bc654de
children
rev   line source
Chris@909 1 # Redmine - project management software
Chris@909 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
Chris@909 3 #
Chris@909 4 # This program is free software; you can redistribute it and/or
Chris@909 5 # modify it under the terms of the GNU General Public License
Chris@909 6 # as published by the Free Software Foundation; either version 2
Chris@909 7 # of the License, or (at your option) any later version.
Chris@909 8 #
Chris@909 9 # This program is distributed in the hope that it will be useful,
Chris@909 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@909 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@909 12 # GNU General Public License for more details.
Chris@909 13 #
Chris@909 14 # You should have received a copy of the GNU General Public License
Chris@909 15 # along with this program; if not, write to the Free Software
Chris@909 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@909 17
Chris@909 18 require File.expand_path('../../test_helper', __FILE__)
Chris@909 19
Chris@909 20 class IssueTest < ActiveSupport::TestCase
Chris@909 21 fixtures :projects, :users, :members, :member_roles, :roles,
Chris@909 22 :trackers, :projects_trackers,
Chris@909 23 :enabled_modules,
Chris@909 24 :versions,
Chris@909 25 :issue_statuses, :issue_categories, :issue_relations, :workflows,
Chris@909 26 :enumerations,
Chris@909 27 :issues,
Chris@909 28 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
Chris@909 29 :time_entries
Chris@909 30
Chris@909 31 def test_create
Chris@909 32 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 33 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 34 :subject => 'test_create',
Chris@909 35 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
Chris@909 36 assert issue.save
Chris@909 37 issue.reload
Chris@909 38 assert_equal 1.5, issue.estimated_hours
Chris@909 39 end
Chris@909 40
Chris@909 41 def test_create_minimal
Chris@909 42 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 43 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 44 :subject => 'test_create')
Chris@909 45 assert issue.save
Chris@909 46 assert issue.description.nil?
Chris@909 47 end
Chris@909 48
Chris@909 49 def test_create_with_required_custom_field
Chris@909 50 field = IssueCustomField.find_by_name('Database')
Chris@909 51 field.update_attribute(:is_required, true)
Chris@909 52
Chris@909 53 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@909 54 :status_id => 1, :subject => 'test_create',
Chris@909 55 :description => 'IssueTest#test_create_with_required_custom_field')
Chris@909 56 assert issue.available_custom_fields.include?(field)
Chris@909 57 # No value for the custom field
Chris@909 58 assert !issue.save
Chris@909 59 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
Chris@909 60 # Blank value
Chris@909 61 issue.custom_field_values = { field.id => '' }
Chris@909 62 assert !issue.save
Chris@909 63 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
Chris@909 64 # Invalid value
Chris@909 65 issue.custom_field_values = { field.id => 'SQLServer' }
Chris@909 66 assert !issue.save
Chris@909 67 assert_equal I18n.translate('activerecord.errors.messages.invalid'), issue.errors.on(:custom_values)
Chris@909 68 # Valid value
Chris@909 69 issue.custom_field_values = { field.id => 'PostgreSQL' }
Chris@909 70 assert issue.save
Chris@909 71 issue.reload
Chris@909 72 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
Chris@909 73 end
Chris@909 74
Chris@909 75 def test_create_with_group_assignment
Chris@909 76 with_settings :issue_group_assignment => '1' do
Chris@909 77 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
Chris@909 78 :subject => 'Group assignment',
Chris@909 79 :assigned_to_id => 11).save
Chris@909 80 issue = Issue.first(:order => 'id DESC')
Chris@909 81 assert_kind_of Group, issue.assigned_to
Chris@909 82 assert_equal Group.find(11), issue.assigned_to
Chris@909 83 end
Chris@909 84 end
Chris@909 85
Chris@909 86 def assert_visibility_match(user, issues)
Chris@909 87 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
Chris@909 88 end
Chris@909 89
Chris@909 90 def test_visible_scope_for_anonymous
Chris@909 91 # Anonymous user should see issues of public projects only
Chris@909 92 issues = Issue.visible(User.anonymous).all
Chris@909 93 assert issues.any?
Chris@909 94 assert_nil issues.detect {|issue| !issue.project.is_public?}
Chris@909 95 assert_nil issues.detect {|issue| issue.is_private?}
Chris@909 96 assert_visibility_match User.anonymous, issues
Chris@909 97 end
Chris@909 98
Chris@909 99 def test_visible_scope_for_anonymous_with_own_issues_visibility
Chris@909 100 Role.anonymous.update_attribute :issues_visibility, 'own'
Chris@909 101 Issue.create!(:project_id => 1, :tracker_id => 1,
Chris@909 102 :author_id => User.anonymous.id,
Chris@909 103 :subject => 'Issue by anonymous')
Chris@909 104
Chris@909 105 issues = Issue.visible(User.anonymous).all
Chris@909 106 assert issues.any?
Chris@909 107 assert_nil issues.detect {|issue| issue.author != User.anonymous}
Chris@909 108 assert_visibility_match User.anonymous, issues
Chris@909 109 end
Chris@909 110
Chris@909 111 def test_visible_scope_for_anonymous_without_view_issues_permissions
Chris@909 112 # Anonymous user should not see issues without permission
Chris@909 113 Role.anonymous.remove_permission!(:view_issues)
Chris@909 114 issues = Issue.visible(User.anonymous).all
Chris@909 115 assert issues.empty?
Chris@909 116 assert_visibility_match User.anonymous, issues
Chris@909 117 end
Chris@909 118
Chris@909 119 def test_visible_scope_for_non_member
Chris@909 120 user = User.find(9)
Chris@909 121 assert user.projects.empty?
Chris@909 122 # Non member user should see issues of public projects only
Chris@909 123 issues = Issue.visible(user).all
Chris@909 124 assert issues.any?
Chris@909 125 assert_nil issues.detect {|issue| !issue.project.is_public?}
Chris@909 126 assert_nil issues.detect {|issue| issue.is_private?}
Chris@909 127 assert_visibility_match user, issues
Chris@909 128 end
Chris@909 129
Chris@909 130 def test_visible_scope_for_non_member_with_own_issues_visibility
Chris@909 131 Role.non_member.update_attribute :issues_visibility, 'own'
Chris@909 132 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
Chris@909 133 user = User.find(9)
Chris@909 134
Chris@909 135 issues = Issue.visible(user).all
Chris@909 136 assert issues.any?
Chris@909 137 assert_nil issues.detect {|issue| issue.author != user}
Chris@909 138 assert_visibility_match user, issues
Chris@909 139 end
Chris@909 140
Chris@909 141 def test_visible_scope_for_non_member_without_view_issues_permissions
Chris@909 142 # Non member user should not see issues without permission
Chris@909 143 Role.non_member.remove_permission!(:view_issues)
Chris@909 144 user = User.find(9)
Chris@909 145 assert user.projects.empty?
Chris@909 146 issues = Issue.visible(user).all
Chris@909 147 assert issues.empty?
Chris@909 148 assert_visibility_match user, issues
Chris@909 149 end
Chris@909 150
Chris@909 151 def test_visible_scope_for_member
Chris@909 152 user = User.find(9)
Chris@909 153 # User should see issues of projects for which he has view_issues permissions only
Chris@909 154 Role.non_member.remove_permission!(:view_issues)
Chris@909 155 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
Chris@909 156 issues = Issue.visible(user).all
Chris@909 157 assert issues.any?
Chris@909 158 assert_nil issues.detect {|issue| issue.project_id != 3}
Chris@909 159 assert_nil issues.detect {|issue| issue.is_private?}
Chris@909 160 assert_visibility_match user, issues
Chris@909 161 end
Chris@909 162
Chris@909 163 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
Chris@909 164 user = User.find(8)
Chris@909 165 assert user.groups.any?
Chris@909 166 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
Chris@909 167 Role.non_member.remove_permission!(:view_issues)
Chris@909 168
Chris@909 169 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 170 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 171 :subject => 'Assignment test',
Chris@909 172 :assigned_to => user.groups.first,
Chris@909 173 :is_private => true)
Chris@909 174
Chris@909 175 Role.find(2).update_attribute :issues_visibility, 'default'
Chris@909 176 issues = Issue.visible(User.find(8)).all
Chris@909 177 assert issues.any?
Chris@909 178 assert issues.include?(issue)
Chris@909 179
Chris@909 180 Role.find(2).update_attribute :issues_visibility, 'own'
Chris@909 181 issues = Issue.visible(User.find(8)).all
Chris@909 182 assert issues.any?
Chris@909 183 assert issues.include?(issue)
Chris@909 184 end
Chris@909 185
Chris@909 186 def test_visible_scope_for_admin
Chris@909 187 user = User.find(1)
Chris@909 188 user.members.each(&:destroy)
Chris@909 189 assert user.projects.empty?
Chris@909 190 issues = Issue.visible(user).all
Chris@909 191 assert issues.any?
Chris@909 192 # Admin should see issues on private projects that he does not belong to
Chris@909 193 assert issues.detect {|issue| !issue.project.is_public?}
Chris@909 194 # Admin should see private issues of other users
Chris@909 195 assert issues.detect {|issue| issue.is_private? && issue.author != user}
Chris@909 196 assert_visibility_match user, issues
Chris@909 197 end
Chris@909 198
Chris@909 199 def test_visible_scope_with_project
Chris@909 200 project = Project.find(1)
Chris@909 201 issues = Issue.visible(User.find(2), :project => project).all
Chris@909 202 projects = issues.collect(&:project).uniq
Chris@909 203 assert_equal 1, projects.size
Chris@909 204 assert_equal project, projects.first
Chris@909 205 end
Chris@909 206
Chris@909 207 def test_visible_scope_with_project_and_subprojects
Chris@909 208 project = Project.find(1)
Chris@909 209 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
Chris@909 210 projects = issues.collect(&:project).uniq
Chris@909 211 assert projects.size > 1
Chris@909 212 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
Chris@909 213 end
Chris@909 214
Chris@909 215 def test_visible_and_nested_set_scopes
Chris@909 216 assert_equal 0, Issue.find(1).descendants.visible.all.size
Chris@909 217 end
Chris@909 218
Chris@909 219 def test_errors_full_messages_should_include_custom_fields_errors
Chris@909 220 field = IssueCustomField.find_by_name('Database')
Chris@909 221
Chris@909 222 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@909 223 :status_id => 1, :subject => 'test_create',
Chris@909 224 :description => 'IssueTest#test_create_with_required_custom_field')
Chris@909 225 assert issue.available_custom_fields.include?(field)
Chris@909 226 # Invalid value
Chris@909 227 issue.custom_field_values = { field.id => 'SQLServer' }
Chris@909 228
Chris@909 229 assert !issue.valid?
Chris@909 230 assert_equal 1, issue.errors.full_messages.size
Chris@909 231 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
Chris@909 232 issue.errors.full_messages.first
Chris@909 233 end
Chris@909 234
Chris@909 235 def test_update_issue_with_required_custom_field
Chris@909 236 field = IssueCustomField.find_by_name('Database')
Chris@909 237 field.update_attribute(:is_required, true)
Chris@909 238
Chris@909 239 issue = Issue.find(1)
Chris@909 240 assert_nil issue.custom_value_for(field)
Chris@909 241 assert issue.available_custom_fields.include?(field)
Chris@909 242 # No change to custom values, issue can be saved
Chris@909 243 assert issue.save
Chris@909 244 # Blank value
Chris@909 245 issue.custom_field_values = { field.id => '' }
Chris@909 246 assert !issue.save
Chris@909 247 # Valid value
Chris@909 248 issue.custom_field_values = { field.id => 'PostgreSQL' }
Chris@909 249 assert issue.save
Chris@909 250 issue.reload
Chris@909 251 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
Chris@909 252 end
Chris@909 253
Chris@909 254 def test_should_not_update_attributes_if_custom_fields_validation_fails
Chris@909 255 issue = Issue.find(1)
Chris@909 256 field = IssueCustomField.find_by_name('Database')
Chris@909 257 assert issue.available_custom_fields.include?(field)
Chris@909 258
Chris@909 259 issue.custom_field_values = { field.id => 'Invalid' }
Chris@909 260 issue.subject = 'Should be not be saved'
Chris@909 261 assert !issue.save
Chris@909 262
Chris@909 263 issue.reload
Chris@909 264 assert_equal "Can't print recipes", issue.subject
Chris@909 265 end
Chris@909 266
Chris@909 267 def test_should_not_recreate_custom_values_objects_on_update
Chris@909 268 field = IssueCustomField.find_by_name('Database')
Chris@909 269
Chris@909 270 issue = Issue.find(1)
Chris@909 271 issue.custom_field_values = { field.id => 'PostgreSQL' }
Chris@909 272 assert issue.save
Chris@909 273 custom_value = issue.custom_value_for(field)
Chris@909 274 issue.reload
Chris@909 275 issue.custom_field_values = { field.id => 'MySQL' }
Chris@909 276 assert issue.save
Chris@909 277 issue.reload
Chris@909 278 assert_equal custom_value.id, issue.custom_value_for(field).id
Chris@909 279 end
Chris@909 280
Chris@909 281 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
Chris@909 282 issue = Issue.new(:project_id => 1)
Chris@909 283 issue.attributes = {:tracker_id => 1, :author_id => 1, :status_id => 1, :subject => 'Test', :custom_field_values => {'2' => 'Test'}}
Chris@909 284 issue.save!
Chris@909 285
Chris@909 286 assert !Tracker.find(2).custom_field_ids.include?(2)
Chris@909 287
Chris@909 288 issue = Issue.find(issue.id)
Chris@909 289 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
Chris@909 290
Chris@909 291 issue = Issue.find(issue.id)
Chris@909 292 custom_value = issue.custom_value_for(2)
Chris@909 293 assert_not_nil custom_value
Chris@909 294 assert_equal 'Test', custom_value.value
Chris@909 295 end
Chris@909 296
Chris@909 297 def test_assigning_tracker_id_should_reload_custom_fields_values
Chris@909 298 issue = Issue.new(:project => Project.find(1))
Chris@909 299 assert issue.custom_field_values.empty?
Chris@909 300 issue.tracker_id = 1
Chris@909 301 assert issue.custom_field_values.any?
Chris@909 302 end
Chris@909 303
Chris@909 304 def test_assigning_attributes_should_assign_tracker_id_first
Chris@909 305 attributes = ActiveSupport::OrderedHash.new
Chris@909 306 attributes['custom_field_values'] = { '1' => 'MySQL' }
Chris@909 307 attributes['tracker_id'] = '1'
Chris@909 308 issue = Issue.new(:project => Project.find(1))
Chris@909 309 issue.attributes = attributes
Chris@909 310 assert_not_nil issue.custom_value_for(1)
Chris@909 311 assert_equal 'MySQL', issue.custom_value_for(1).value
Chris@909 312 end
Chris@909 313
Chris@909 314 def test_should_update_issue_with_disabled_tracker
Chris@909 315 p = Project.find(1)
Chris@909 316 issue = Issue.find(1)
Chris@909 317
Chris@909 318 p.trackers.delete(issue.tracker)
Chris@909 319 assert !p.trackers.include?(issue.tracker)
Chris@909 320
Chris@909 321 issue.reload
Chris@909 322 issue.subject = 'New subject'
Chris@909 323 assert issue.save
Chris@909 324 end
Chris@909 325
Chris@909 326 def test_should_not_set_a_disabled_tracker
Chris@909 327 p = Project.find(1)
Chris@909 328 p.trackers.delete(Tracker.find(2))
Chris@909 329
Chris@909 330 issue = Issue.find(1)
Chris@909 331 issue.tracker_id = 2
Chris@909 332 issue.subject = 'New subject'
Chris@909 333 assert !issue.save
Chris@909 334 assert_not_nil issue.errors[:tracker_id]
Chris@909 335 end
Chris@909 336
Chris@909 337 def test_category_based_assignment
Chris@909 338 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 339 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 340 :subject => 'Assignment test',
Chris@909 341 :description => 'Assignment test', :category_id => 1)
Chris@909 342 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
Chris@909 343 end
Chris@909 344
Chris@909 345 def test_new_statuses_allowed_to
Chris@909 346 Workflow.delete_all
Chris@909 347
Chris@909 348 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 2, :author => false, :assignee => false)
Chris@909 349 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 3, :author => true, :assignee => false)
Chris@909 350 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 4, :author => false, :assignee => true)
Chris@909 351 Workflow.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1, :new_status_id => 5, :author => true, :assignee => true)
Chris@909 352 status = IssueStatus.find(1)
Chris@909 353 role = Role.find(1)
Chris@909 354 tracker = Tracker.find(1)
Chris@909 355 user = User.find(2)
Chris@909 356
Chris@909 357 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1)
Chris@909 358 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
Chris@909 359
Chris@909 360 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user)
Chris@909 361 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@909 362
Chris@909 363 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :assigned_to => user)
Chris@909 364 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@909 365
Chris@909 366 issue = Issue.generate!(:tracker => tracker, :status => status, :project_id => 1, :author => user, :assigned_to => user)
Chris@909 367 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@909 368 end
Chris@909 369
Chris@909 370 def test_copy
Chris@909 371 issue = Issue.new.copy_from(1)
Chris@909 372 assert issue.save
Chris@909 373 issue.reload
Chris@909 374 orig = Issue.find(1)
Chris@909 375 assert_equal orig.subject, issue.subject
Chris@909 376 assert_equal orig.tracker, issue.tracker
Chris@909 377 assert_equal "125", issue.custom_value_for(2).value
Chris@909 378 end
Chris@909 379
Chris@909 380 def test_copy_should_copy_status
Chris@909 381 orig = Issue.find(8)
Chris@909 382 assert orig.status != IssueStatus.default
Chris@909 383
Chris@909 384 issue = Issue.new.copy_from(orig)
Chris@909 385 assert issue.save
Chris@909 386 issue.reload
Chris@909 387 assert_equal orig.status, issue.status
Chris@909 388 end
Chris@909 389
Chris@909 390 def test_should_close_duplicates
Chris@909 391 # Create 3 issues
Chris@909 392 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@909 393 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 394 :subject => 'Duplicates test', :description => 'Duplicates test')
Chris@909 395 assert issue1.save
Chris@909 396 issue2 = issue1.clone
Chris@909 397 assert issue2.save
Chris@909 398 issue3 = issue1.clone
Chris@909 399 assert issue3.save
Chris@909 400
Chris@909 401 # 2 is a dupe of 1
Chris@909 402 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@909 403 # And 3 is a dupe of 2
Chris@909 404 IssueRelation.create(:issue_from => issue3, :issue_to => issue2, :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@909 405 # And 3 is a dupe of 1 (circular duplicates)
Chris@909 406 IssueRelation.create(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@909 407
Chris@909 408 assert issue1.reload.duplicates.include?(issue2)
Chris@909 409
Chris@909 410 # Closing issue 1
Chris@909 411 issue1.init_journal(User.find(:first), "Closing issue1")
Chris@909 412 issue1.status = IssueStatus.find :first, :conditions => {:is_closed => true}
Chris@909 413 assert issue1.save
Chris@909 414 # 2 and 3 should be also closed
Chris@909 415 assert issue2.reload.closed?
Chris@909 416 assert issue3.reload.closed?
Chris@909 417 end
Chris@909 418
Chris@909 419 def test_should_not_close_duplicated_issue
Chris@909 420 # Create 3 issues
Chris@909 421 issue1 = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@909 422 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 423 :subject => 'Duplicates test', :description => 'Duplicates test')
Chris@909 424 assert issue1.save
Chris@909 425 issue2 = issue1.clone
Chris@909 426 assert issue2.save
Chris@909 427
Chris@909 428 # 2 is a dupe of 1
Chris@909 429 IssueRelation.create(:issue_from => issue2, :issue_to => issue1, :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@909 430 # 2 is a dup of 1 but 1 is not a duplicate of 2
Chris@909 431 assert !issue2.reload.duplicates.include?(issue1)
Chris@909 432
Chris@909 433 # Closing issue 2
Chris@909 434 issue2.init_journal(User.find(:first), "Closing issue2")
Chris@909 435 issue2.status = IssueStatus.find :first, :conditions => {:is_closed => true}
Chris@909 436 assert issue2.save
Chris@909 437 # 1 should not be also closed
Chris@909 438 assert !issue1.reload.closed?
Chris@909 439 end
Chris@909 440
Chris@909 441 def test_assignable_versions
Chris@909 442 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
Chris@909 443 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
Chris@909 444 end
Chris@909 445
Chris@909 446 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
Chris@909 447 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 1, :subject => 'New issue')
Chris@909 448 assert !issue.save
Chris@909 449 assert_not_nil issue.errors[:fixed_version_id]
Chris@909 450 end
Chris@909 451
Chris@909 452 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
Chris@909 453 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 2, :subject => 'New issue')
Chris@909 454 assert !issue.save
Chris@909 455 assert_not_nil issue.errors[:fixed_version_id]
Chris@909 456 end
Chris@909 457
Chris@909 458 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
Chris@909 459 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :fixed_version_id => 3, :subject => 'New issue')
Chris@909 460 assert issue.save
Chris@909 461 end
Chris@909 462
Chris@909 463 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
Chris@909 464 issue = Issue.find(11)
Chris@909 465 assert_equal 'closed', issue.fixed_version.status
Chris@909 466 issue.subject = 'Subject changed'
Chris@909 467 assert issue.save
Chris@909 468 end
Chris@909 469
Chris@909 470 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
Chris@909 471 issue = Issue.find(11)
Chris@909 472 issue.status_id = 1
Chris@909 473 assert !issue.save
Chris@909 474 assert_not_nil issue.errors[:base]
Chris@909 475 end
Chris@909 476
Chris@909 477 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
Chris@909 478 issue = Issue.find(11)
Chris@909 479 issue.status_id = 1
Chris@909 480 issue.fixed_version_id = 3
Chris@909 481 assert issue.save
Chris@909 482 end
Chris@909 483
Chris@909 484 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
Chris@909 485 issue = Issue.find(12)
Chris@909 486 assert_equal 'locked', issue.fixed_version.status
Chris@909 487 issue.status_id = 1
Chris@909 488 assert issue.save
Chris@909 489 end
Chris@909 490
Chris@909 491 def test_move_to_another_project_with_same_category
Chris@909 492 issue = Issue.find(1)
Chris@909 493 assert issue.move_to_project(Project.find(2))
Chris@909 494 issue.reload
Chris@909 495 assert_equal 2, issue.project_id
Chris@909 496 # Category changes
Chris@909 497 assert_equal 4, issue.category_id
Chris@909 498 # Make sure time entries were move to the target project
Chris@909 499 assert_equal 2, issue.time_entries.first.project_id
Chris@909 500 end
Chris@909 501
Chris@909 502 def test_move_to_another_project_without_same_category
Chris@909 503 issue = Issue.find(2)
Chris@909 504 assert issue.move_to_project(Project.find(2))
Chris@909 505 issue.reload
Chris@909 506 assert_equal 2, issue.project_id
Chris@909 507 # Category cleared
Chris@909 508 assert_nil issue.category_id
Chris@909 509 end
Chris@909 510
Chris@909 511 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
Chris@909 512 issue = Issue.find(1)
Chris@909 513 issue.update_attribute(:fixed_version_id, 1)
Chris@909 514 assert issue.move_to_project(Project.find(2))
Chris@909 515 issue.reload
Chris@909 516 assert_equal 2, issue.project_id
Chris@909 517 # Cleared fixed_version
Chris@909 518 assert_equal nil, issue.fixed_version
Chris@909 519 end
Chris@909 520
Chris@909 521 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
Chris@909 522 issue = Issue.find(1)
Chris@909 523 issue.update_attribute(:fixed_version_id, 4)
Chris@909 524 assert issue.move_to_project(Project.find(5))
Chris@909 525 issue.reload
Chris@909 526 assert_equal 5, issue.project_id
Chris@909 527 # Keep fixed_version
Chris@909 528 assert_equal 4, issue.fixed_version_id
Chris@909 529 end
Chris@909 530
Chris@909 531 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
Chris@909 532 issue = Issue.find(1)
Chris@909 533 issue.update_attribute(:fixed_version_id, 1)
Chris@909 534 assert issue.move_to_project(Project.find(5))
Chris@909 535 issue.reload
Chris@909 536 assert_equal 5, issue.project_id
Chris@909 537 # Cleared fixed_version
Chris@909 538 assert_equal nil, issue.fixed_version
Chris@909 539 end
Chris@909 540
Chris@909 541 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
Chris@909 542 issue = Issue.find(1)
Chris@909 543 issue.update_attribute(:fixed_version_id, 7)
Chris@909 544 assert issue.move_to_project(Project.find(2))
Chris@909 545 issue.reload
Chris@909 546 assert_equal 2, issue.project_id
Chris@909 547 # Keep fixed_version
Chris@909 548 assert_equal 7, issue.fixed_version_id
Chris@909 549 end
Chris@909 550
Chris@909 551 def test_move_to_another_project_with_disabled_tracker
Chris@909 552 issue = Issue.find(1)
Chris@909 553 target = Project.find(2)
Chris@909 554 target.tracker_ids = [3]
Chris@909 555 target.save
Chris@909 556 assert_equal false, issue.move_to_project(target)
Chris@909 557 issue.reload
Chris@909 558 assert_equal 1, issue.project_id
Chris@909 559 end
Chris@909 560
Chris@909 561 def test_copy_to_the_same_project
Chris@909 562 issue = Issue.find(1)
Chris@909 563 copy = nil
Chris@909 564 assert_difference 'Issue.count' do
Chris@909 565 copy = issue.move_to_project(issue.project, nil, :copy => true)
Chris@909 566 end
Chris@909 567 assert_kind_of Issue, copy
Chris@909 568 assert_equal issue.project, copy.project
Chris@909 569 assert_equal "125", copy.custom_value_for(2).value
Chris@909 570 end
Chris@909 571
Chris@909 572 def test_copy_to_another_project_and_tracker
Chris@909 573 issue = Issue.find(1)
Chris@909 574 copy = nil
Chris@909 575 assert_difference 'Issue.count' do
Chris@909 576 copy = issue.move_to_project(Project.find(3), Tracker.find(2), :copy => true)
Chris@909 577 end
Chris@909 578 copy.reload
Chris@909 579 assert_kind_of Issue, copy
Chris@909 580 assert_equal Project.find(3), copy.project
Chris@909 581 assert_equal Tracker.find(2), copy.tracker
Chris@909 582 # Custom field #2 is not associated with target tracker
Chris@909 583 assert_nil copy.custom_value_for(2)
Chris@909 584 end
Chris@909 585
Chris@909 586 context "#move_to_project" do
Chris@909 587 context "as a copy" do
Chris@909 588 setup do
Chris@909 589 @issue = Issue.find(1)
Chris@909 590 @copy = nil
Chris@909 591 end
Chris@909 592
Chris@909 593 should "not create a journal" do
Chris@909 594 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
Chris@909 595 assert_equal 0, @copy.reload.journals.size
Chris@909 596 end
Chris@909 597
Chris@909 598 should "allow assigned_to changes" do
Chris@909 599 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:assigned_to_id => 3}})
Chris@909 600 assert_equal 3, @copy.assigned_to_id
Chris@909 601 end
Chris@909 602
Chris@909 603 should "allow status changes" do
Chris@909 604 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:status_id => 2}})
Chris@909 605 assert_equal 2, @copy.status_id
Chris@909 606 end
Chris@909 607
Chris@909 608 should "allow start date changes" do
Chris@909 609 date = Date.today
Chris@909 610 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
Chris@909 611 assert_equal date, @copy.start_date
Chris@909 612 end
Chris@909 613
Chris@909 614 should "allow due date changes" do
Chris@909 615 date = Date.today
Chris@909 616 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:due_date => date}})
Chris@909 617
Chris@909 618 assert_equal date, @copy.due_date
Chris@909 619 end
Chris@909 620
Chris@909 621 should "set current user as author" do
Chris@909 622 User.current = User.find(9)
Chris@909 623 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {}})
Chris@909 624
Chris@909 625 assert_equal User.current, @copy.author
Chris@909 626 end
Chris@909 627
Chris@909 628 should "keep journal notes" do
Chris@909 629 date = Date.today
Chris@909 630 notes = "Notes added when copying"
Chris@909 631 User.current = User.find(9)
Chris@909 632 @issue.init_journal(User.current, notes)
Chris@909 633 @copy = @issue.move_to_project(Project.find(3), Tracker.find(2), {:copy => true, :attributes => {:start_date => date}})
Chris@909 634
Chris@909 635 assert_equal 1, @copy.journals.size
Chris@909 636 journal = @copy.journals.first
Chris@909 637 assert_equal 0, journal.details.size
Chris@909 638 assert_equal notes, journal.notes
Chris@909 639 end
Chris@909 640 end
Chris@909 641 end
Chris@909 642
Chris@909 643 def test_recipients_should_not_include_users_that_cannot_view_the_issue
Chris@909 644 issue = Issue.find(12)
Chris@909 645 assert issue.recipients.include?(issue.author.mail)
Chris@909 646 # move the issue to a private project
Chris@909 647 copy = issue.move_to_project(Project.find(5), Tracker.find(2), :copy => true)
Chris@909 648 # author is not a member of project anymore
Chris@909 649 assert !copy.recipients.include?(copy.author.mail)
Chris@909 650 end
Chris@909 651
Chris@909 652 def test_recipients_should_include_the_assigned_group_members
Chris@909 653 group_member = User.generate_with_protected!
Chris@909 654 group = Group.generate!
Chris@909 655 group.users << group_member
Chris@909 656
Chris@909 657 issue = Issue.find(12)
Chris@909 658 issue.assigned_to = group
Chris@909 659 assert issue.recipients.include?(group_member.mail)
Chris@909 660 end
Chris@909 661
Chris@909 662 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
Chris@909 663 user = User.find(3)
Chris@909 664 issue = Issue.find(9)
Chris@909 665 Watcher.create!(:user => user, :watchable => issue)
Chris@909 666 assert issue.watched_by?(user)
Chris@909 667 assert !issue.watcher_recipients.include?(user.mail)
Chris@909 668 end
Chris@909 669
Chris@909 670 def test_issue_destroy
Chris@909 671 Issue.find(1).destroy
Chris@909 672 assert_nil Issue.find_by_id(1)
Chris@909 673 assert_nil TimeEntry.find_by_issue_id(1)
Chris@909 674 end
Chris@909 675
Chris@909 676 def test_blocked
Chris@909 677 blocked_issue = Issue.find(9)
Chris@909 678 blocking_issue = Issue.find(10)
Chris@909 679
Chris@909 680 assert blocked_issue.blocked?
Chris@909 681 assert !blocking_issue.blocked?
Chris@909 682 end
Chris@909 683
Chris@909 684 def test_blocked_issues_dont_allow_closed_statuses
Chris@909 685 blocked_issue = Issue.find(9)
Chris@909 686
Chris@909 687 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
Chris@909 688 assert !allowed_statuses.empty?
Chris@909 689 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
Chris@909 690 assert closed_statuses.empty?
Chris@909 691 end
Chris@909 692
Chris@909 693 def test_unblocked_issues_allow_closed_statuses
Chris@909 694 blocking_issue = Issue.find(10)
Chris@909 695
Chris@909 696 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
Chris@909 697 assert !allowed_statuses.empty?
Chris@909 698 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
Chris@909 699 assert !closed_statuses.empty?
Chris@909 700 end
Chris@909 701
Chris@909 702 def test_rescheduling_an_issue_should_reschedule_following_issue
Chris@909 703 issue1 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
Chris@909 704 issue2 = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1, :status_id => 1, :subject => '-', :start_date => Date.today, :due_date => Date.today + 2)
Chris@909 705 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 706 assert_equal issue1.due_date + 1, issue2.reload.start_date
Chris@909 707
Chris@909 708 issue1.due_date = Date.today + 5
Chris@909 709 issue1.save!
Chris@909 710 assert_equal issue1.due_date + 1, issue2.reload.start_date
Chris@909 711 end
Chris@909 712
Chris@909 713 def test_overdue
Chris@909 714 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
Chris@909 715 assert !Issue.new(:due_date => Date.today).overdue?
Chris@909 716 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
Chris@909 717 assert !Issue.new(:due_date => nil).overdue?
Chris@909 718 assert !Issue.new(:due_date => 1.day.ago.to_date, :status => IssueStatus.find(:first, :conditions => {:is_closed => true})).overdue?
Chris@909 719 end
Chris@909 720
Chris@909 721 context "#behind_schedule?" do
Chris@909 722 should "be false if the issue has no start_date" do
Chris@909 723 assert !Issue.new(:start_date => nil, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
Chris@909 724 end
Chris@909 725
Chris@909 726 should "be false if the issue has no end_date" do
Chris@909 727 assert !Issue.new(:start_date => 1.day.from_now.to_date, :due_date => nil, :done_ratio => 0).behind_schedule?
Chris@909 728 end
Chris@909 729
Chris@909 730 should "be false if the issue has more done than it's calendar time" do
Chris@909 731 assert !Issue.new(:start_date => 50.days.ago.to_date, :due_date => 50.days.from_now.to_date, :done_ratio => 90).behind_schedule?
Chris@909 732 end
Chris@909 733
Chris@909 734 should "be true if the issue hasn't been started at all" do
Chris@909 735 assert Issue.new(:start_date => 1.day.ago.to_date, :due_date => 1.day.from_now.to_date, :done_ratio => 0).behind_schedule?
Chris@909 736 end
Chris@909 737
Chris@909 738 should "be true if the issue has used more calendar time than it's done ratio" do
Chris@909 739 assert Issue.new(:start_date => 100.days.ago.to_date, :due_date => Date.today, :done_ratio => 90).behind_schedule?
Chris@909 740 end
Chris@909 741 end
Chris@909 742
Chris@909 743 context "#assignable_users" do
Chris@909 744 should "be Users" do
Chris@909 745 assert_kind_of User, Issue.find(1).assignable_users.first
Chris@909 746 end
Chris@909 747
Chris@909 748 should "include the issue author" do
Chris@909 749 project = Project.find(1)
Chris@909 750 non_project_member = User.generate!
Chris@909 751 issue = Issue.generate_for_project!(project, :author => non_project_member)
Chris@909 752
Chris@909 753 assert issue.assignable_users.include?(non_project_member)
Chris@909 754 end
Chris@909 755
Chris@909 756 should "include the current assignee" do
Chris@909 757 project = Project.find(1)
Chris@909 758 user = User.generate!
Chris@909 759 issue = Issue.generate_for_project!(project, :assigned_to => user)
Chris@909 760 user.lock!
Chris@909 761
Chris@909 762 assert Issue.find(issue.id).assignable_users.include?(user)
Chris@909 763 end
Chris@909 764
Chris@909 765 should "not show the issue author twice" do
Chris@909 766 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
Chris@909 767 assert_equal 2, assignable_user_ids.length
Chris@909 768
Chris@909 769 assignable_user_ids.each do |user_id|
Chris@909 770 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length, "User #{user_id} appears more or less than once"
Chris@909 771 end
Chris@909 772 end
Chris@909 773
Chris@909 774 context "with issue_group_assignment" do
Chris@909 775 should "include groups" do
Chris@909 776 issue = Issue.new(:project => Project.find(2))
Chris@909 777
Chris@909 778 with_settings :issue_group_assignment => '1' do
Chris@909 779 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
Chris@909 780 assert issue.assignable_users.include?(Group.find(11))
Chris@909 781 end
Chris@909 782 end
Chris@909 783 end
Chris@909 784
Chris@909 785 context "without issue_group_assignment" do
Chris@909 786 should "not include groups" do
Chris@909 787 issue = Issue.new(:project => Project.find(2))
Chris@909 788
Chris@909 789 with_settings :issue_group_assignment => '0' do
Chris@909 790 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
Chris@909 791 assert !issue.assignable_users.include?(Group.find(11))
Chris@909 792 end
Chris@909 793 end
Chris@909 794 end
Chris@909 795 end
Chris@909 796
Chris@909 797 def test_create_should_send_email_notification
Chris@909 798 ActionMailer::Base.deliveries.clear
Chris@909 799 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@909 800 :author_id => 3, :status_id => 1,
Chris@909 801 :priority => IssuePriority.all.first,
Chris@909 802 :subject => 'test_create', :estimated_hours => '1:30')
Chris@909 803
Chris@909 804 assert issue.save
Chris@909 805 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@909 806 end
Chris@909 807
Chris@909 808 def test_stale_issue_should_not_send_email_notification
Chris@909 809 ActionMailer::Base.deliveries.clear
Chris@909 810 issue = Issue.find(1)
Chris@909 811 stale = Issue.find(1)
Chris@909 812
Chris@909 813 issue.init_journal(User.find(1))
Chris@909 814 issue.subject = 'Subjet update'
Chris@909 815 assert issue.save
Chris@909 816 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@909 817 ActionMailer::Base.deliveries.clear
Chris@909 818
Chris@909 819 stale.init_journal(User.find(1))
Chris@909 820 stale.subject = 'Another subjet update'
Chris@909 821 assert_raise ActiveRecord::StaleObjectError do
Chris@909 822 stale.save
Chris@909 823 end
Chris@909 824 assert ActionMailer::Base.deliveries.empty?
Chris@909 825 end
Chris@909 826
Chris@909 827 def test_journalized_description
Chris@909 828 IssueCustomField.delete_all
Chris@909 829
Chris@909 830 i = Issue.first
Chris@909 831 old_description = i.description
Chris@909 832 new_description = "This is the new description"
Chris@909 833
Chris@909 834 i.init_journal(User.find(2))
Chris@909 835 i.description = new_description
Chris@909 836 assert_difference 'Journal.count', 1 do
Chris@909 837 assert_difference 'JournalDetail.count', 1 do
Chris@909 838 i.save!
Chris@909 839 end
Chris@909 840 end
Chris@909 841
Chris@909 842 detail = JournalDetail.first(:order => 'id DESC')
Chris@909 843 assert_equal i, detail.journal.journalized
Chris@909 844 assert_equal 'attr', detail.property
Chris@909 845 assert_equal 'description', detail.prop_key
Chris@909 846 assert_equal old_description, detail.old_value
Chris@909 847 assert_equal new_description, detail.value
Chris@909 848 end
Chris@909 849
Chris@909 850 def test_blank_descriptions_should_not_be_journalized
Chris@909 851 IssueCustomField.delete_all
Chris@909 852 Issue.update_all("description = NULL", "id=1")
Chris@909 853
Chris@909 854 i = Issue.find(1)
Chris@909 855 i.init_journal(User.find(2))
Chris@909 856 i.subject = "blank description"
Chris@909 857 i.description = "\r\n"
Chris@909 858
Chris@909 859 assert_difference 'Journal.count', 1 do
Chris@909 860 assert_difference 'JournalDetail.count', 1 do
Chris@909 861 i.save!
Chris@909 862 end
Chris@909 863 end
Chris@909 864 end
Chris@909 865
Chris@909 866 def test_description_eol_should_be_normalized
Chris@909 867 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
Chris@909 868 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
Chris@909 869 end
Chris@909 870
Chris@909 871 def test_saving_twice_should_not_duplicate_journal_details
Chris@909 872 i = Issue.find(:first)
Chris@909 873 i.init_journal(User.find(2), 'Some notes')
Chris@909 874 # initial changes
Chris@909 875 i.subject = 'New subject'
Chris@909 876 i.done_ratio = i.done_ratio + 10
Chris@909 877 assert_difference 'Journal.count' do
Chris@909 878 assert i.save
Chris@909 879 end
Chris@909 880 # 1 more change
Chris@909 881 i.priority = IssuePriority.find(:first, :conditions => ["id <> ?", i.priority_id])
Chris@909 882 assert_no_difference 'Journal.count' do
Chris@909 883 assert_difference 'JournalDetail.count', 1 do
Chris@909 884 i.save
Chris@909 885 end
Chris@909 886 end
Chris@909 887 # no more change
Chris@909 888 assert_no_difference 'Journal.count' do
Chris@909 889 assert_no_difference 'JournalDetail.count' do
Chris@909 890 i.save
Chris@909 891 end
Chris@909 892 end
Chris@909 893 end
Chris@909 894
Chris@909 895 def test_all_dependent_issues
Chris@909 896 IssueRelation.delete_all
Chris@909 897 assert IssueRelation.create!(:issue_from => Issue.find(1),
Chris@909 898 :issue_to => Issue.find(2),
Chris@909 899 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 900 assert IssueRelation.create!(:issue_from => Issue.find(2),
Chris@909 901 :issue_to => Issue.find(3),
Chris@909 902 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 903 assert IssueRelation.create!(:issue_from => Issue.find(3),
Chris@909 904 :issue_to => Issue.find(8),
Chris@909 905 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 906
Chris@909 907 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
Chris@909 908 end
Chris@909 909
Chris@909 910 def test_all_dependent_issues_with_persistent_circular_dependency
Chris@909 911 IssueRelation.delete_all
Chris@909 912 assert IssueRelation.create!(:issue_from => Issue.find(1),
Chris@909 913 :issue_to => Issue.find(2),
Chris@909 914 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 915 assert IssueRelation.create!(:issue_from => Issue.find(2),
Chris@909 916 :issue_to => Issue.find(3),
Chris@909 917 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 918 # Validation skipping
Chris@909 919 assert IssueRelation.new(:issue_from => Issue.find(3),
Chris@909 920 :issue_to => Issue.find(1),
Chris@909 921 :relation_type => IssueRelation::TYPE_PRECEDES).save(false)
Chris@909 922
Chris@909 923 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
Chris@909 924 end
Chris@909 925
Chris@909 926 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
Chris@909 927 IssueRelation.delete_all
Chris@909 928 assert IssueRelation.create!(:issue_from => Issue.find(1),
Chris@909 929 :issue_to => Issue.find(2),
Chris@909 930 :relation_type => IssueRelation::TYPE_RELATES)
Chris@909 931 assert IssueRelation.create!(:issue_from => Issue.find(2),
Chris@909 932 :issue_to => Issue.find(3),
Chris@909 933 :relation_type => IssueRelation::TYPE_RELATES)
Chris@909 934 assert IssueRelation.create!(:issue_from => Issue.find(3),
Chris@909 935 :issue_to => Issue.find(8),
Chris@909 936 :relation_type => IssueRelation::TYPE_RELATES)
Chris@909 937 # Validation skipping
Chris@909 938 assert IssueRelation.new(:issue_from => Issue.find(8),
Chris@909 939 :issue_to => Issue.find(2),
Chris@909 940 :relation_type => IssueRelation::TYPE_RELATES).save(false)
Chris@909 941 assert IssueRelation.new(:issue_from => Issue.find(3),
Chris@909 942 :issue_to => Issue.find(1),
Chris@909 943 :relation_type => IssueRelation::TYPE_RELATES).save(false)
Chris@909 944
Chris@909 945 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
Chris@909 946 end
Chris@909 947
Chris@909 948 context "#done_ratio" do
Chris@909 949 setup do
Chris@909 950 @issue = Issue.find(1)
Chris@909 951 @issue_status = IssueStatus.find(1)
Chris@909 952 @issue_status.update_attribute(:default_done_ratio, 50)
Chris@909 953 @issue2 = Issue.find(2)
Chris@909 954 @issue_status2 = IssueStatus.find(2)
Chris@909 955 @issue_status2.update_attribute(:default_done_ratio, 0)
Chris@909 956 end
Chris@909 957
Chris@909 958 context "with Setting.issue_done_ratio using the issue_field" do
Chris@909 959 setup do
Chris@909 960 Setting.issue_done_ratio = 'issue_field'
Chris@909 961 end
Chris@909 962
Chris@909 963 should "read the issue's field" do
Chris@909 964 assert_equal 0, @issue.done_ratio
Chris@909 965 assert_equal 30, @issue2.done_ratio
Chris@909 966 end
Chris@909 967 end
Chris@909 968
Chris@909 969 context "with Setting.issue_done_ratio using the issue_status" do
Chris@909 970 setup do
Chris@909 971 Setting.issue_done_ratio = 'issue_status'
Chris@909 972 end
Chris@909 973
Chris@909 974 should "read the Issue Status's default done ratio" do
Chris@909 975 assert_equal 50, @issue.done_ratio
Chris@909 976 assert_equal 0, @issue2.done_ratio
Chris@909 977 end
Chris@909 978 end
Chris@909 979 end
Chris@909 980
Chris@909 981 context "#update_done_ratio_from_issue_status" do
Chris@909 982 setup do
Chris@909 983 @issue = Issue.find(1)
Chris@909 984 @issue_status = IssueStatus.find(1)
Chris@909 985 @issue_status.update_attribute(:default_done_ratio, 50)
Chris@909 986 @issue2 = Issue.find(2)
Chris@909 987 @issue_status2 = IssueStatus.find(2)
Chris@909 988 @issue_status2.update_attribute(:default_done_ratio, 0)
Chris@909 989 end
Chris@909 990
Chris@909 991 context "with Setting.issue_done_ratio using the issue_field" do
Chris@909 992 setup do
Chris@909 993 Setting.issue_done_ratio = 'issue_field'
Chris@909 994 end
Chris@909 995
Chris@909 996 should "not change the issue" do
Chris@909 997 @issue.update_done_ratio_from_issue_status
Chris@909 998 @issue2.update_done_ratio_from_issue_status
Chris@909 999
Chris@909 1000 assert_equal 0, @issue.read_attribute(:done_ratio)
Chris@909 1001 assert_equal 30, @issue2.read_attribute(:done_ratio)
Chris@909 1002 end
Chris@909 1003 end
Chris@909 1004
Chris@909 1005 context "with Setting.issue_done_ratio using the issue_status" do
Chris@909 1006 setup do
Chris@909 1007 Setting.issue_done_ratio = 'issue_status'
Chris@909 1008 end
Chris@909 1009
Chris@909 1010 should "change the issue's done ratio" do
Chris@909 1011 @issue.update_done_ratio_from_issue_status
Chris@909 1012 @issue2.update_done_ratio_from_issue_status
Chris@909 1013
Chris@909 1014 assert_equal 50, @issue.read_attribute(:done_ratio)
Chris@909 1015 assert_equal 0, @issue2.read_attribute(:done_ratio)
Chris@909 1016 end
Chris@909 1017 end
Chris@909 1018 end
Chris@909 1019
Chris@909 1020 test "#by_tracker" do
Chris@909 1021 User.current = User.anonymous
Chris@909 1022 groups = Issue.by_tracker(Project.find(1))
Chris@909 1023 assert_equal 3, groups.size
Chris@909 1024 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1025 end
Chris@909 1026
Chris@909 1027 test "#by_version" do
Chris@909 1028 User.current = User.anonymous
Chris@909 1029 groups = Issue.by_version(Project.find(1))
Chris@909 1030 assert_equal 3, groups.size
Chris@909 1031 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1032 end
Chris@909 1033
Chris@909 1034 test "#by_priority" do
Chris@909 1035 User.current = User.anonymous
Chris@909 1036 groups = Issue.by_priority(Project.find(1))
Chris@909 1037 assert_equal 4, groups.size
Chris@909 1038 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1039 end
Chris@909 1040
Chris@909 1041 test "#by_category" do
Chris@909 1042 User.current = User.anonymous
Chris@909 1043 groups = Issue.by_category(Project.find(1))
Chris@909 1044 assert_equal 2, groups.size
Chris@909 1045 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1046 end
Chris@909 1047
Chris@909 1048 test "#by_assigned_to" do
Chris@909 1049 User.current = User.anonymous
Chris@909 1050 groups = Issue.by_assigned_to(Project.find(1))
Chris@909 1051 assert_equal 2, groups.size
Chris@909 1052 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1053 end
Chris@909 1054
Chris@909 1055 test "#by_author" do
Chris@909 1056 User.current = User.anonymous
Chris@909 1057 groups = Issue.by_author(Project.find(1))
Chris@909 1058 assert_equal 4, groups.size
Chris@909 1059 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1060 end
Chris@909 1061
Chris@909 1062 test "#by_subproject" do
Chris@909 1063 User.current = User.anonymous
Chris@909 1064 groups = Issue.by_subproject(Project.find(1))
Chris@909 1065 # Private descendant not visible
Chris@909 1066 assert_equal 1, groups.size
Chris@909 1067 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@909 1068 end
Chris@909 1069
Chris@909 1070 context ".allowed_target_projects_on_move" do
Chris@909 1071 should "return all active projects for admin users" do
Chris@909 1072 User.current = User.find(1)
Chris@909 1073 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
Chris@909 1074 end
Chris@909 1075
Chris@909 1076 should "return allowed projects for non admin users" do
Chris@909 1077 User.current = User.find(2)
Chris@909 1078 Role.non_member.remove_permission! :move_issues
Chris@909 1079 assert_equal 3, Issue.allowed_target_projects_on_move.size
Chris@909 1080
Chris@909 1081 Role.non_member.add_permission! :move_issues
Chris@909 1082 assert_equal Project.active.count, Issue.allowed_target_projects_on_move.size
Chris@909 1083 end
Chris@909 1084 end
Chris@909 1085
Chris@909 1086 def test_recently_updated_with_limit_scopes
Chris@909 1087 #should return the last updated issue
Chris@909 1088 assert_equal 1, Issue.recently_updated.with_limit(1).length
Chris@909 1089 assert_equal Issue.find(:first, :order => "updated_on DESC"), Issue.recently_updated.with_limit(1).first
Chris@909 1090 end
Chris@909 1091
Chris@909 1092 def test_on_active_projects_scope
Chris@909 1093 assert Project.find(2).archive
Chris@909 1094
Chris@909 1095 before = Issue.on_active_project.length
Chris@909 1096 # test inclusion to results
Chris@909 1097 issue = Issue.generate_for_project!(Project.find(1), :tracker => Project.find(2).trackers.first)
Chris@909 1098 assert_equal before + 1, Issue.on_active_project.length
Chris@909 1099
Chris@909 1100 # Move to an archived project
Chris@909 1101 issue.project = Project.find(2)
Chris@909 1102 assert issue.save
Chris@909 1103 assert_equal before, Issue.on_active_project.length
Chris@909 1104 end
Chris@909 1105
Chris@909 1106 context "Issue#recipients" do
Chris@909 1107 setup do
Chris@909 1108 @project = Project.find(1)
Chris@909 1109 @author = User.generate_with_protected!
Chris@909 1110 @assignee = User.generate_with_protected!
Chris@909 1111 @issue = Issue.generate_for_project!(@project, :assigned_to => @assignee, :author => @author)
Chris@909 1112 end
Chris@909 1113
Chris@909 1114 should "include project recipients" do
Chris@909 1115 assert @project.recipients.present?
Chris@909 1116 @project.recipients.each do |project_recipient|
Chris@909 1117 assert @issue.recipients.include?(project_recipient)
Chris@909 1118 end
Chris@909 1119 end
Chris@909 1120
Chris@909 1121 should "include the author if the author is active" do
Chris@909 1122 assert @issue.author, "No author set for Issue"
Chris@909 1123 assert @issue.recipients.include?(@issue.author.mail)
Chris@909 1124 end
Chris@909 1125
Chris@909 1126 should "include the assigned to user if the assigned to user is active" do
Chris@909 1127 assert @issue.assigned_to, "No assigned_to set for Issue"
Chris@909 1128 assert @issue.recipients.include?(@issue.assigned_to.mail)
Chris@909 1129 end
Chris@909 1130
Chris@909 1131 should "not include users who opt out of all email" do
Chris@909 1132 @author.update_attribute(:mail_notification, :none)
Chris@909 1133
Chris@909 1134 assert !@issue.recipients.include?(@issue.author.mail)
Chris@909 1135 end
Chris@909 1136
Chris@909 1137 should "not include the issue author if they are only notified of assigned issues" do
Chris@909 1138 @author.update_attribute(:mail_notification, :only_assigned)
Chris@909 1139
Chris@909 1140 assert !@issue.recipients.include?(@issue.author.mail)
Chris@909 1141 end
Chris@909 1142
Chris@909 1143 should "not include the assigned user if they are only notified of owned issues" do
Chris@909 1144 @assignee.update_attribute(:mail_notification, :only_owner)
Chris@909 1145
Chris@909 1146 assert !@issue.recipients.include?(@issue.assigned_to.mail)
Chris@909 1147 end
Chris@909 1148
Chris@909 1149 end
Chris@909 1150 end