annotate test/unit/issue_test.rb @ 1628:9c5f8e24dadc live tip

Quieten this cron script
author Chris Cannam
date Tue, 25 Aug 2020 11:38:49 +0100
parents dffacf8a6908
children
rev   line source
Chris@245 1 # Redmine - project management software
Chris@1494 2 # Copyright (C) 2006-2014 Jean-Philippe Lang
Chris@0 3 #
Chris@0 4 # This program is free software; you can redistribute it and/or
Chris@0 5 # modify it under the terms of the GNU General Public License
Chris@0 6 # as published by the Free Software Foundation; either version 2
Chris@0 7 # of the License, or (at your option) any later version.
Chris@441 8 #
Chris@0 9 # This program is distributed in the hope that it will be useful,
Chris@0 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 12 # GNU General Public License for more details.
Chris@441 13 #
Chris@0 14 # You should have received a copy of the GNU General Public License
Chris@0 15 # along with this program; if not, write to the Free Software
Chris@0 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@0 17
Chris@119 18 require File.expand_path('../../test_helper', __FILE__)
Chris@0 19
Chris@0 20 class IssueTest < ActiveSupport::TestCase
Chris@0 21 fixtures :projects, :users, :members, :member_roles, :roles,
Chris@1115 22 :groups_users,
Chris@0 23 :trackers, :projects_trackers,
Chris@0 24 :enabled_modules,
Chris@0 25 :versions,
Chris@441 26 :issue_statuses, :issue_categories, :issue_relations, :workflows,
Chris@0 27 :enumerations,
Chris@1115 28 :issues, :journals, :journal_details,
Chris@0 29 :custom_fields, :custom_fields_projects, :custom_fields_trackers, :custom_values,
Chris@0 30 :time_entries
Chris@0 31
Chris@1115 32 include Redmine::I18n
Chris@1115 33
Chris@1115 34 def teardown
Chris@1115 35 User.current = nil
Chris@1115 36 end
Chris@1115 37
Chris@1464 38 def test_initialize
Chris@1464 39 issue = Issue.new
Chris@1464 40
Chris@1464 41 assert_nil issue.project_id
Chris@1464 42 assert_nil issue.tracker_id
Chris@1464 43 assert_nil issue.author_id
Chris@1464 44 assert_nil issue.assigned_to_id
Chris@1464 45 assert_nil issue.category_id
Chris@1464 46
Chris@1464 47 assert_equal IssueStatus.default, issue.status
Chris@1464 48 assert_equal IssuePriority.default, issue.priority
Chris@1464 49 end
Chris@1464 50
Chris@0 51 def test_create
Chris@909 52 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 53 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 54 :subject => 'test_create',
Chris@909 55 :description => 'IssueTest#test_create', :estimated_hours => '1:30')
Chris@0 56 assert issue.save
Chris@0 57 issue.reload
Chris@0 58 assert_equal 1.5, issue.estimated_hours
Chris@0 59 end
Chris@441 60
Chris@0 61 def test_create_minimal
Chris@909 62 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 63 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 64 :subject => 'test_create')
Chris@0 65 assert issue.save
Chris@0 66 assert issue.description.nil?
Chris@1115 67 assert_nil issue.estimated_hours
Chris@1115 68 end
Chris@1115 69
Chris@1115 70 def test_start_date_format_should_be_validated
Chris@1115 71 set_language_if_valid 'en'
Chris@1115 72 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
Chris@1115 73 issue = Issue.new(:start_date => invalid_date)
Chris@1115 74 assert !issue.valid?
Chris@1115 75 assert_include 'Start date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
Chris@1115 76 end
Chris@1115 77 end
Chris@1115 78
Chris@1115 79 def test_due_date_format_should_be_validated
Chris@1115 80 set_language_if_valid 'en'
Chris@1115 81 ['2012', 'ABC', '2012-15-20'].each do |invalid_date|
Chris@1115 82 issue = Issue.new(:due_date => invalid_date)
Chris@1115 83 assert !issue.valid?
Chris@1115 84 assert_include 'Due date is not a valid date', issue.errors.full_messages, "No error found for invalid date #{invalid_date}"
Chris@1115 85 end
Chris@1115 86 end
Chris@1115 87
Chris@1115 88 def test_due_date_lesser_than_start_date_should_not_validate
Chris@1115 89 set_language_if_valid 'en'
Chris@1115 90 issue = Issue.new(:start_date => '2012-10-06', :due_date => '2012-10-02')
Chris@1115 91 assert !issue.valid?
Chris@1115 92 assert_include 'Due date must be greater than start date', issue.errors.full_messages
Chris@0 93 end
Chris@441 94
Chris@1464 95 def test_start_date_lesser_than_soonest_start_should_not_validate_on_create
Chris@1464 96 issue = Issue.generate(:start_date => '2013-06-04')
Chris@1464 97 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
Chris@1464 98 assert !issue.valid?
Chris@1464 99 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
Chris@1464 100 end
Chris@1464 101
Chris@1464 102 def test_start_date_lesser_than_soonest_start_should_not_validate_on_update_if_changed
Chris@1464 103 issue = Issue.generate!(:start_date => '2013-06-04')
Chris@1464 104 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
Chris@1464 105 issue.start_date = '2013-06-07'
Chris@1464 106 assert !issue.valid?
Chris@1464 107 assert_include "Start date cannot be earlier than 06/10/2013 because of preceding issues", issue.errors.full_messages
Chris@1464 108 end
Chris@1464 109
Chris@1464 110 def test_start_date_lesser_than_soonest_start_should_validate_on_update_if_unchanged
Chris@1464 111 issue = Issue.generate!(:start_date => '2013-06-04')
Chris@1464 112 issue.stubs(:soonest_start).returns(Date.parse('2013-06-10'))
Chris@1464 113 assert issue.valid?
Chris@1464 114 end
Chris@1464 115
Chris@1464 116 def test_estimated_hours_should_be_validated
Chris@1464 117 set_language_if_valid 'en'
Chris@1464 118 ['-2'].each do |invalid|
Chris@1464 119 issue = Issue.new(:estimated_hours => invalid)
Chris@1464 120 assert !issue.valid?
Chris@1464 121 assert_include 'Estimated time is invalid', issue.errors.full_messages
Chris@1464 122 end
Chris@1464 123 end
Chris@1464 124
Chris@0 125 def test_create_with_required_custom_field
Chris@1115 126 set_language_if_valid 'en'
Chris@0 127 field = IssueCustomField.find_by_name('Database')
Chris@0 128 field.update_attribute(:is_required, true)
Chris@441 129
Chris@909 130 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@909 131 :status_id => 1, :subject => 'test_create',
Chris@909 132 :description => 'IssueTest#test_create_with_required_custom_field')
Chris@0 133 assert issue.available_custom_fields.include?(field)
Chris@0 134 # No value for the custom field
Chris@0 135 assert !issue.save
Chris@1115 136 assert_equal ["Database can't be blank"], issue.errors.full_messages
Chris@0 137 # Blank value
Chris@0 138 issue.custom_field_values = { field.id => '' }
Chris@0 139 assert !issue.save
Chris@1115 140 assert_equal ["Database can't be blank"], issue.errors.full_messages
Chris@0 141 # Invalid value
Chris@0 142 issue.custom_field_values = { field.id => 'SQLServer' }
Chris@0 143 assert !issue.save
Chris@1115 144 assert_equal ["Database is not included in the list"], issue.errors.full_messages
Chris@0 145 # Valid value
Chris@0 146 issue.custom_field_values = { field.id => 'PostgreSQL' }
Chris@0 147 assert issue.save
Chris@0 148 issue.reload
Chris@0 149 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
Chris@0 150 end
Chris@441 151
Chris@909 152 def test_create_with_group_assignment
Chris@909 153 with_settings :issue_group_assignment => '1' do
Chris@909 154 assert Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
Chris@909 155 :subject => 'Group assignment',
Chris@909 156 :assigned_to_id => 11).save
Chris@1517 157 issue = Issue.order('id DESC').first
Chris@909 158 assert_kind_of Group, issue.assigned_to
Chris@909 159 assert_equal Group.find(11), issue.assigned_to
Chris@909 160 end
Chris@909 161 end
Chris@909 162
Chris@1115 163 def test_create_with_parent_issue_id
Chris@1115 164 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1115 165 :author_id => 1, :subject => 'Group assignment',
Chris@1115 166 :parent_issue_id => 1)
Chris@1115 167 assert_save issue
Chris@1115 168 assert_equal 1, issue.parent_issue_id
Chris@1115 169 assert_equal Issue.find(1), issue.parent
Chris@1115 170 end
Chris@1115 171
Chris@1115 172 def test_create_with_sharp_parent_issue_id
Chris@1115 173 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1115 174 :author_id => 1, :subject => 'Group assignment',
Chris@1115 175 :parent_issue_id => "#1")
Chris@1115 176 assert_save issue
Chris@1115 177 assert_equal 1, issue.parent_issue_id
Chris@1115 178 assert_equal Issue.find(1), issue.parent
Chris@1115 179 end
Chris@1115 180
Chris@1115 181 def test_create_with_invalid_parent_issue_id
Chris@1115 182 set_language_if_valid 'en'
Chris@1115 183 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1115 184 :author_id => 1, :subject => 'Group assignment',
Chris@1115 185 :parent_issue_id => '01ABC')
Chris@1115 186 assert !issue.save
Chris@1115 187 assert_equal '01ABC', issue.parent_issue_id
Chris@1115 188 assert_include 'Parent task is invalid', issue.errors.full_messages
Chris@1115 189 end
Chris@1115 190
Chris@1115 191 def test_create_with_invalid_sharp_parent_issue_id
Chris@1115 192 set_language_if_valid 'en'
Chris@1115 193 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1115 194 :author_id => 1, :subject => 'Group assignment',
Chris@1115 195 :parent_issue_id => '#01ABC')
Chris@1115 196 assert !issue.save
Chris@1115 197 assert_equal '#01ABC', issue.parent_issue_id
Chris@1115 198 assert_include 'Parent task is invalid', issue.errors.full_messages
Chris@1115 199 end
Chris@1115 200
Chris@441 201 def assert_visibility_match(user, issues)
Chris@441 202 assert_equal issues.collect(&:id).sort, Issue.all.select {|issue| issue.visible?(user)}.collect(&:id).sort
Chris@441 203 end
Chris@441 204
Chris@0 205 def test_visible_scope_for_anonymous
Chris@0 206 # Anonymous user should see issues of public projects only
Chris@0 207 issues = Issue.visible(User.anonymous).all
Chris@0 208 assert issues.any?
Chris@0 209 assert_nil issues.detect {|issue| !issue.project.is_public?}
Chris@441 210 assert_nil issues.detect {|issue| issue.is_private?}
Chris@441 211 assert_visibility_match User.anonymous, issues
Chris@441 212 end
Chris@441 213
Chris@441 214 def test_visible_scope_for_anonymous_without_view_issues_permissions
Chris@0 215 # Anonymous user should not see issues without permission
Chris@0 216 Role.anonymous.remove_permission!(:view_issues)
Chris@0 217 issues = Issue.visible(User.anonymous).all
Chris@0 218 assert issues.empty?
Chris@441 219 assert_visibility_match User.anonymous, issues
Chris@0 220 end
Chris@441 221
Chris@1115 222 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_default
Chris@1115 223 assert Role.anonymous.update_attribute(:issues_visibility, 'default')
Chris@1115 224 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
Chris@1115 225 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
Chris@1115 226 assert !issue.visible?(User.anonymous)
Chris@1115 227 end
Chris@1115 228
Chris@1115 229 def test_anonymous_should_not_see_private_issues_with_issues_visibility_set_to_own
Chris@1115 230 assert Role.anonymous.update_attribute(:issues_visibility, 'own')
Chris@1115 231 issue = Issue.generate!(:author => User.anonymous, :assigned_to => User.anonymous, :is_private => true)
Chris@1115 232 assert_nil Issue.where(:id => issue.id).visible(User.anonymous).first
Chris@1115 233 assert !issue.visible?(User.anonymous)
Chris@1115 234 end
Chris@1115 235
Chris@441 236 def test_visible_scope_for_non_member
Chris@0 237 user = User.find(9)
Chris@0 238 assert user.projects.empty?
Chris@0 239 # Non member user should see issues of public projects only
Chris@0 240 issues = Issue.visible(user).all
Chris@0 241 assert issues.any?
Chris@0 242 assert_nil issues.detect {|issue| !issue.project.is_public?}
Chris@441 243 assert_nil issues.detect {|issue| issue.is_private?}
Chris@441 244 assert_visibility_match user, issues
Chris@441 245 end
Chris@441 246
Chris@441 247 def test_visible_scope_for_non_member_with_own_issues_visibility
Chris@441 248 Role.non_member.update_attribute :issues_visibility, 'own'
Chris@441 249 Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 9, :subject => 'Issue by non member')
Chris@441 250 user = User.find(9)
Chris@441 251
Chris@441 252 issues = Issue.visible(user).all
Chris@441 253 assert issues.any?
Chris@441 254 assert_nil issues.detect {|issue| issue.author != user}
Chris@441 255 assert_visibility_match user, issues
Chris@441 256 end
Chris@441 257
Chris@441 258 def test_visible_scope_for_non_member_without_view_issues_permissions
Chris@0 259 # Non member user should not see issues without permission
Chris@0 260 Role.non_member.remove_permission!(:view_issues)
Chris@441 261 user = User.find(9)
Chris@441 262 assert user.projects.empty?
Chris@0 263 issues = Issue.visible(user).all
Chris@0 264 assert issues.empty?
Chris@441 265 assert_visibility_match user, issues
Chris@441 266 end
Chris@441 267
Chris@441 268 def test_visible_scope_for_member
Chris@441 269 user = User.find(9)
Chris@1464 270 # User should see issues of projects for which user has view_issues permissions only
Chris@441 271 Role.non_member.remove_permission!(:view_issues)
Chris@441 272 Member.create!(:principal => user, :project_id => 3, :role_ids => [2])
Chris@0 273 issues = Issue.visible(user).all
Chris@0 274 assert issues.any?
Chris@441 275 assert_nil issues.detect {|issue| issue.project_id != 3}
Chris@441 276 assert_nil issues.detect {|issue| issue.is_private?}
Chris@441 277 assert_visibility_match user, issues
Chris@0 278 end
Chris@441 279
Chris@909 280 def test_visible_scope_for_member_with_groups_should_return_assigned_issues
Chris@909 281 user = User.find(8)
Chris@909 282 assert user.groups.any?
Chris@909 283 Member.create!(:principal => user.groups.first, :project_id => 1, :role_ids => [2])
Chris@909 284 Role.non_member.remove_permission!(:view_issues)
Chris@1464 285
Chris@909 286 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 287 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 288 :subject => 'Assignment test',
Chris@909 289 :assigned_to => user.groups.first,
Chris@909 290 :is_private => true)
Chris@1464 291
Chris@909 292 Role.find(2).update_attribute :issues_visibility, 'default'
Chris@909 293 issues = Issue.visible(User.find(8)).all
Chris@909 294 assert issues.any?
Chris@909 295 assert issues.include?(issue)
Chris@1464 296
Chris@909 297 Role.find(2).update_attribute :issues_visibility, 'own'
Chris@909 298 issues = Issue.visible(User.find(8)).all
Chris@909 299 assert issues.any?
Chris@909 300 assert issues.include?(issue)
Chris@909 301 end
Chris@909 302
Chris@0 303 def test_visible_scope_for_admin
Chris@0 304 user = User.find(1)
Chris@0 305 user.members.each(&:destroy)
Chris@0 306 assert user.projects.empty?
Chris@0 307 issues = Issue.visible(user).all
Chris@0 308 assert issues.any?
Chris@1464 309 # Admin should see issues on private projects that admin does not belong to
Chris@0 310 assert issues.detect {|issue| !issue.project.is_public?}
Chris@441 311 # Admin should see private issues of other users
Chris@441 312 assert issues.detect {|issue| issue.is_private? && issue.author != user}
Chris@441 313 assert_visibility_match user, issues
Chris@0 314 end
Chris@441 315
Chris@441 316 def test_visible_scope_with_project
Chris@441 317 project = Project.find(1)
Chris@441 318 issues = Issue.visible(User.find(2), :project => project).all
Chris@441 319 projects = issues.collect(&:project).uniq
Chris@441 320 assert_equal 1, projects.size
Chris@441 321 assert_equal project, projects.first
Chris@441 322 end
Chris@441 323
Chris@441 324 def test_visible_scope_with_project_and_subprojects
Chris@441 325 project = Project.find(1)
Chris@441 326 issues = Issue.visible(User.find(2), :project => project, :with_subprojects => true).all
Chris@441 327 projects = issues.collect(&:project).uniq
Chris@441 328 assert projects.size > 1
Chris@441 329 assert_equal [], projects.select {|p| !p.is_or_is_descendant_of?(project)}
Chris@441 330 end
Chris@441 331
Chris@441 332 def test_visible_and_nested_set_scopes
Chris@1517 333 user = User.generate!
Chris@1517 334 parent = Issue.generate!(:assigned_to => user)
Chris@1517 335 assert parent.visible?(user)
Chris@1517 336 child1 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
Chris@1517 337 child2 = Issue.generate!(:parent_issue_id => parent.id, :assigned_to => user)
Chris@1517 338 parent.reload
Chris@1517 339 child1.reload
Chris@1517 340 child2.reload
Chris@1517 341 assert child1.visible?(user)
Chris@1517 342 assert child2.visible?(user)
Chris@1517 343 assert_equal 2, parent.descendants.count
Chris@1517 344 assert_equal 2, parent.descendants.visible(user).count
Chris@1517 345 # awesome_nested_set 2-1-stable branch has regression.
Chris@1517 346 # https://github.com/collectiveidea/awesome_nested_set/commit/3d5ac746542b564f6586c2316180254b088bebb6
Chris@1517 347 # ActiveRecord::StatementInvalid: SQLite3::SQLException: ambiguous column name: lft:
Chris@1517 348 assert_equal 2, parent.descendants.collect{|i| i}.size
Chris@1517 349 assert_equal 2, parent.descendants.visible(user).collect{|i| i}.size
Chris@441 350 end
Chris@441 351
Chris@1115 352 def test_open_scope
Chris@1115 353 issues = Issue.open.all
Chris@1115 354 assert_nil issues.detect(&:closed?)
Chris@1115 355 end
Chris@1115 356
Chris@1115 357 def test_open_scope_with_arg
Chris@1115 358 issues = Issue.open(false).all
Chris@1115 359 assert_equal issues, issues.select(&:closed?)
Chris@1115 360 end
Chris@1115 361
Chris@1464 362 def test_fixed_version_scope_with_a_version_should_return_its_fixed_issues
Chris@1464 363 version = Version.find(2)
Chris@1464 364 assert version.fixed_issues.any?
Chris@1464 365 assert_equal version.fixed_issues.to_a.sort, Issue.fixed_version(version).to_a.sort
Chris@1464 366 end
Chris@1464 367
Chris@1464 368 def test_fixed_version_scope_with_empty_array_should_return_no_result
Chris@1464 369 assert_equal 0, Issue.fixed_version([]).count
Chris@1464 370 end
Chris@1464 371
Chris@0 372 def test_errors_full_messages_should_include_custom_fields_errors
Chris@0 373 field = IssueCustomField.find_by_name('Database')
Chris@441 374
Chris@909 375 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@909 376 :status_id => 1, :subject => 'test_create',
Chris@909 377 :description => 'IssueTest#test_create_with_required_custom_field')
Chris@0 378 assert issue.available_custom_fields.include?(field)
Chris@0 379 # Invalid value
Chris@0 380 issue.custom_field_values = { field.id => 'SQLServer' }
Chris@441 381
Chris@0 382 assert !issue.valid?
Chris@0 383 assert_equal 1, issue.errors.full_messages.size
Chris@909 384 assert_equal "Database #{I18n.translate('activerecord.errors.messages.inclusion')}",
Chris@909 385 issue.errors.full_messages.first
Chris@0 386 end
Chris@441 387
Chris@0 388 def test_update_issue_with_required_custom_field
Chris@0 389 field = IssueCustomField.find_by_name('Database')
Chris@0 390 field.update_attribute(:is_required, true)
Chris@441 391
Chris@0 392 issue = Issue.find(1)
Chris@0 393 assert_nil issue.custom_value_for(field)
Chris@0 394 assert issue.available_custom_fields.include?(field)
Chris@0 395 # No change to custom values, issue can be saved
Chris@0 396 assert issue.save
Chris@0 397 # Blank value
Chris@0 398 issue.custom_field_values = { field.id => '' }
Chris@0 399 assert !issue.save
Chris@0 400 # Valid value
Chris@0 401 issue.custom_field_values = { field.id => 'PostgreSQL' }
Chris@0 402 assert issue.save
Chris@0 403 issue.reload
Chris@0 404 assert_equal 'PostgreSQL', issue.custom_value_for(field).value
Chris@0 405 end
Chris@441 406
Chris@0 407 def test_should_not_update_attributes_if_custom_fields_validation_fails
Chris@0 408 issue = Issue.find(1)
Chris@0 409 field = IssueCustomField.find_by_name('Database')
Chris@0 410 assert issue.available_custom_fields.include?(field)
Chris@441 411
Chris@0 412 issue.custom_field_values = { field.id => 'Invalid' }
Chris@0 413 issue.subject = 'Should be not be saved'
Chris@0 414 assert !issue.save
Chris@441 415
Chris@0 416 issue.reload
Chris@0 417 assert_equal "Can't print recipes", issue.subject
Chris@0 418 end
Chris@441 419
Chris@0 420 def test_should_not_recreate_custom_values_objects_on_update
Chris@0 421 field = IssueCustomField.find_by_name('Database')
Chris@441 422
Chris@0 423 issue = Issue.find(1)
Chris@0 424 issue.custom_field_values = { field.id => 'PostgreSQL' }
Chris@0 425 assert issue.save
Chris@0 426 custom_value = issue.custom_value_for(field)
Chris@0 427 issue.reload
Chris@0 428 issue.custom_field_values = { field.id => 'MySQL' }
Chris@0 429 assert issue.save
Chris@0 430 issue.reload
Chris@0 431 assert_equal custom_value.id, issue.custom_value_for(field).id
Chris@0 432 end
Chris@441 433
Chris@909 434 def test_should_not_update_custom_fields_on_changing_tracker_with_different_custom_fields
Chris@1115 435 issue = Issue.create!(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@1115 436 :status_id => 1, :subject => 'Test',
Chris@1115 437 :custom_field_values => {'2' => 'Test'})
Chris@909 438 assert !Tracker.find(2).custom_field_ids.include?(2)
Chris@909 439
Chris@909 440 issue = Issue.find(issue.id)
Chris@909 441 issue.attributes = {:tracker_id => 2, :custom_field_values => {'1' => ''}}
Chris@909 442
Chris@909 443 issue = Issue.find(issue.id)
Chris@909 444 custom_value = issue.custom_value_for(2)
Chris@909 445 assert_not_nil custom_value
Chris@909 446 assert_equal 'Test', custom_value.value
Chris@909 447 end
Chris@909 448
Chris@0 449 def test_assigning_tracker_id_should_reload_custom_fields_values
Chris@0 450 issue = Issue.new(:project => Project.find(1))
Chris@0 451 assert issue.custom_field_values.empty?
Chris@0 452 issue.tracker_id = 1
Chris@0 453 assert issue.custom_field_values.any?
Chris@0 454 end
Chris@441 455
Chris@1115 456 def test_assigning_attributes_should_assign_project_and_tracker_first
Chris@1115 457 seq = sequence('seq')
Chris@1115 458 issue = Issue.new
Chris@1115 459 issue.expects(:project_id=).in_sequence(seq)
Chris@1115 460 issue.expects(:tracker_id=).in_sequence(seq)
Chris@1115 461 issue.expects(:subject=).in_sequence(seq)
Chris@1115 462 issue.attributes = {:tracker_id => 2, :project_id => 1, :subject => 'Test'}
Chris@1115 463 end
Chris@1115 464
Chris@1115 465 def test_assigning_tracker_and_custom_fields_should_assign_custom_fields
Chris@0 466 attributes = ActiveSupport::OrderedHash.new
Chris@0 467 attributes['custom_field_values'] = { '1' => 'MySQL' }
Chris@0 468 attributes['tracker_id'] = '1'
Chris@0 469 issue = Issue.new(:project => Project.find(1))
Chris@0 470 issue.attributes = attributes
Chris@1115 471 assert_equal 'MySQL', issue.custom_field_value(1)
Chris@0 472 end
Chris@441 473
Chris@1464 474 def test_reload_should_reload_custom_field_values
Chris@1464 475 issue = Issue.generate!
Chris@1464 476 issue.custom_field_values = {'2' => 'Foo'}
Chris@1464 477 issue.save!
Chris@1464 478
Chris@1464 479 issue = Issue.order('id desc').first
Chris@1464 480 assert_equal 'Foo', issue.custom_field_value(2)
Chris@1464 481
Chris@1464 482 issue.custom_field_values = {'2' => 'Bar'}
Chris@1464 483 assert_equal 'Bar', issue.custom_field_value(2)
Chris@1464 484
Chris@1464 485 issue.reload
Chris@1464 486 assert_equal 'Foo', issue.custom_field_value(2)
Chris@1464 487 end
Chris@1464 488
Chris@0 489 def test_should_update_issue_with_disabled_tracker
Chris@0 490 p = Project.find(1)
Chris@0 491 issue = Issue.find(1)
Chris@441 492
Chris@0 493 p.trackers.delete(issue.tracker)
Chris@0 494 assert !p.trackers.include?(issue.tracker)
Chris@441 495
Chris@0 496 issue.reload
Chris@0 497 issue.subject = 'New subject'
Chris@0 498 assert issue.save
Chris@0 499 end
Chris@441 500
Chris@0 501 def test_should_not_set_a_disabled_tracker
Chris@0 502 p = Project.find(1)
Chris@0 503 p.trackers.delete(Tracker.find(2))
Chris@441 504
Chris@0 505 issue = Issue.find(1)
Chris@0 506 issue.tracker_id = 2
Chris@0 507 issue.subject = 'New subject'
Chris@0 508 assert !issue.save
Chris@1464 509 assert_not_equal [], issue.errors[:tracker_id]
Chris@0 510 end
Chris@441 511
Chris@0 512 def test_category_based_assignment
Chris@909 513 issue = Issue.create(:project_id => 1, :tracker_id => 1, :author_id => 3,
Chris@909 514 :status_id => 1, :priority => IssuePriority.all.first,
Chris@909 515 :subject => 'Assignment test',
Chris@909 516 :description => 'Assignment test', :category_id => 1)
Chris@0 517 assert_equal IssueCategory.find(1).assigned_to, issue.assigned_to
Chris@0 518 end
Chris@441 519
Chris@245 520 def test_new_statuses_allowed_to
Chris@1115 521 WorkflowTransition.delete_all
Chris@1115 522 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
Chris@1115 523 :old_status_id => 1, :new_status_id => 2,
Chris@1115 524 :author => false, :assignee => false)
Chris@1115 525 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
Chris@1115 526 :old_status_id => 1, :new_status_id => 3,
Chris@1115 527 :author => true, :assignee => false)
Chris@1464 528 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
Chris@1464 529 :old_status_id => 1, :new_status_id => 4,
Chris@1464 530 :author => false, :assignee => true)
Chris@1115 531 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
Chris@1115 532 :old_status_id => 1, :new_status_id => 5,
Chris@1115 533 :author => true, :assignee => true)
Chris@245 534 status = IssueStatus.find(1)
Chris@245 535 role = Role.find(1)
Chris@245 536 tracker = Tracker.find(1)
Chris@245 537 user = User.find(2)
Chris@441 538
Chris@1115 539 issue = Issue.generate!(:tracker => tracker, :status => status,
Chris@1115 540 :project_id => 1, :author_id => 1)
Chris@245 541 assert_equal [1, 2], issue.new_statuses_allowed_to(user).map(&:id)
Chris@441 542
Chris@1115 543 issue = Issue.generate!(:tracker => tracker, :status => status,
Chris@1115 544 :project_id => 1, :author => user)
Chris@909 545 assert_equal [1, 2, 3, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@441 546
Chris@1115 547 issue = Issue.generate!(:tracker => tracker, :status => status,
Chris@1115 548 :project_id => 1, :author_id => 1,
Chris@1115 549 :assigned_to => user)
Chris@909 550 assert_equal [1, 2, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@441 551
Chris@1115 552 issue = Issue.generate!(:tracker => tracker, :status => status,
Chris@1115 553 :project_id => 1, :author => user,
Chris@1115 554 :assigned_to => user)
Chris@245 555 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@1464 556
Chris@1464 557 group = Group.generate!
Chris@1464 558 group.users << user
Chris@1464 559 issue = Issue.generate!(:tracker => tracker, :status => status,
Chris@1464 560 :project_id => 1, :author => user,
Chris@1464 561 :assigned_to => group)
Chris@1464 562 assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
Chris@1464 563 end
Chris@1464 564
Chris@1464 565 def test_new_statuses_allowed_to_should_consider_group_assignment
Chris@1464 566 WorkflowTransition.delete_all
Chris@1464 567 WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
Chris@1464 568 :old_status_id => 1, :new_status_id => 4,
Chris@1464 569 :author => false, :assignee => true)
Chris@1464 570 user = User.find(2)
Chris@1464 571 group = Group.generate!
Chris@1464 572 group.users << user
Chris@1464 573
Chris@1464 574 issue = Issue.generate!(:author_id => 1, :assigned_to => group)
Chris@1464 575 assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
Chris@245 576 end
Chris@441 577
Chris@1115 578 def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
Chris@1115 579 admin = User.find(1)
Chris@1115 580 issue = Issue.find(1)
Chris@1115 581 assert !admin.member_of?(issue.project)
Chris@1464 582 expected_statuses = [issue.status] +
Chris@1517 583 WorkflowTransition.where(:old_status_id => issue.status_id).
Chris@1517 584 map(&:new_status).uniq.sort
Chris@1115 585 assert_equal expected_statuses, issue.new_statuses_allowed_to(admin)
Chris@1115 586 end
Chris@1115 587
Chris@1115 588 def test_new_statuses_allowed_to_should_return_default_and_current_status_when_copying
Chris@1115 589 issue = Issue.find(1).copy
Chris@1115 590 assert_equal [1], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
Chris@1115 591
Chris@1115 592 issue = Issue.find(2).copy
Chris@1115 593 assert_equal [1, 2], issue.new_statuses_allowed_to(User.find(2)).map(&:id)
Chris@1115 594 end
Chris@1115 595
Chris@1115 596 def test_safe_attributes_names_should_not_include_disabled_field
Chris@1115 597 tracker = Tracker.new(:core_fields => %w(assigned_to_id fixed_version_id))
Chris@1115 598
Chris@1115 599 issue = Issue.new(:tracker => tracker)
Chris@1115 600 assert_include 'tracker_id', issue.safe_attribute_names
Chris@1115 601 assert_include 'status_id', issue.safe_attribute_names
Chris@1115 602 assert_include 'subject', issue.safe_attribute_names
Chris@1115 603 assert_include 'description', issue.safe_attribute_names
Chris@1115 604 assert_include 'custom_field_values', issue.safe_attribute_names
Chris@1115 605 assert_include 'custom_fields', issue.safe_attribute_names
Chris@1115 606 assert_include 'lock_version', issue.safe_attribute_names
Chris@1115 607
Chris@1115 608 tracker.core_fields.each do |field|
Chris@1115 609 assert_include field, issue.safe_attribute_names
Chris@1115 610 end
Chris@1115 611
Chris@1115 612 tracker.disabled_core_fields.each do |field|
Chris@1115 613 assert_not_include field, issue.safe_attribute_names
Chris@1115 614 end
Chris@1115 615 end
Chris@1115 616
Chris@1115 617 def test_safe_attributes_should_ignore_disabled_fields
Chris@1115 618 tracker = Tracker.find(1)
Chris@1115 619 tracker.core_fields = %w(assigned_to_id due_date)
Chris@1115 620 tracker.save!
Chris@1115 621
Chris@1115 622 issue = Issue.new(:tracker => tracker)
Chris@1115 623 issue.safe_attributes = {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}
Chris@1115 624 assert_nil issue.start_date
Chris@1115 625 assert_equal Date.parse('2012-07-14'), issue.due_date
Chris@1115 626 end
Chris@1115 627
Chris@1115 628 def test_safe_attributes_should_accept_target_tracker_enabled_fields
Chris@1115 629 source = Tracker.find(1)
Chris@1115 630 source.core_fields = []
Chris@1115 631 source.save!
Chris@1115 632 target = Tracker.find(2)
Chris@1115 633 target.core_fields = %w(assigned_to_id due_date)
Chris@1115 634 target.save!
Chris@1115 635
Chris@1115 636 issue = Issue.new(:tracker => source)
Chris@1115 637 issue.safe_attributes = {'tracker_id' => 2, 'due_date' => '2012-07-14'}
Chris@1115 638 assert_equal target, issue.tracker
Chris@1115 639 assert_equal Date.parse('2012-07-14'), issue.due_date
Chris@1115 640 end
Chris@1115 641
Chris@1115 642 def test_safe_attributes_should_not_include_readonly_fields
Chris@1115 643 WorkflowPermission.delete_all
Chris@1115 644 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 645 :role_id => 1, :field_name => 'due_date',
Chris@1115 646 :rule => 'readonly')
Chris@1115 647 user = User.find(2)
Chris@1115 648
Chris@1115 649 issue = Issue.new(:project_id => 1, :tracker_id => 1)
Chris@1115 650 assert_equal %w(due_date), issue.read_only_attribute_names(user)
Chris@1115 651 assert_not_include 'due_date', issue.safe_attribute_names(user)
Chris@1115 652
Chris@1115 653 issue.send :safe_attributes=, {'start_date' => '2012-07-14', 'due_date' => '2012-07-14'}, user
Chris@1115 654 assert_equal Date.parse('2012-07-14'), issue.start_date
Chris@1115 655 assert_nil issue.due_date
Chris@1115 656 end
Chris@1115 657
Chris@1115 658 def test_safe_attributes_should_not_include_readonly_custom_fields
Chris@1115 659 cf1 = IssueCustomField.create!(:name => 'Writable field',
Chris@1115 660 :field_format => 'string',
Chris@1115 661 :is_for_all => true, :tracker_ids => [1])
Chris@1115 662 cf2 = IssueCustomField.create!(:name => 'Readonly field',
Chris@1115 663 :field_format => 'string',
Chris@1115 664 :is_for_all => true, :tracker_ids => [1])
Chris@1115 665 WorkflowPermission.delete_all
Chris@1115 666 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 667 :role_id => 1, :field_name => cf2.id.to_s,
Chris@1115 668 :rule => 'readonly')
Chris@1115 669 user = User.find(2)
Chris@1115 670 issue = Issue.new(:project_id => 1, :tracker_id => 1)
Chris@1115 671 assert_equal [cf2.id.to_s], issue.read_only_attribute_names(user)
Chris@1115 672 assert_not_include cf2.id.to_s, issue.safe_attribute_names(user)
Chris@1115 673
Chris@1115 674 issue.send :safe_attributes=, {'custom_field_values' => {
Chris@1115 675 cf1.id.to_s => 'value1', cf2.id.to_s => 'value2'
Chris@1115 676 }}, user
Chris@1115 677 assert_equal 'value1', issue.custom_field_value(cf1)
Chris@1115 678 assert_nil issue.custom_field_value(cf2)
Chris@1115 679
Chris@1115 680 issue.send :safe_attributes=, {'custom_fields' => [
Chris@1115 681 {'id' => cf1.id.to_s, 'value' => 'valuea'},
Chris@1115 682 {'id' => cf2.id.to_s, 'value' => 'valueb'}
Chris@1115 683 ]}, user
Chris@1115 684 assert_equal 'valuea', issue.custom_field_value(cf1)
Chris@1115 685 assert_nil issue.custom_field_value(cf2)
Chris@1115 686 end
Chris@1115 687
Chris@1115 688 def test_editable_custom_field_values_should_return_non_readonly_custom_values
Chris@1115 689 cf1 = IssueCustomField.create!(:name => 'Writable field', :field_format => 'string',
Chris@1115 690 :is_for_all => true, :tracker_ids => [1, 2])
Chris@1115 691 cf2 = IssueCustomField.create!(:name => 'Readonly field', :field_format => 'string',
Chris@1115 692 :is_for_all => true, :tracker_ids => [1, 2])
Chris@1115 693 WorkflowPermission.delete_all
Chris@1115 694 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1, :role_id => 1,
Chris@1115 695 :field_name => cf2.id.to_s, :rule => 'readonly')
Chris@1115 696 user = User.find(2)
Chris@1115 697
Chris@1115 698 issue = Issue.new(:project_id => 1, :tracker_id => 1)
Chris@1115 699 values = issue.editable_custom_field_values(user)
Chris@1115 700 assert values.detect {|value| value.custom_field == cf1}
Chris@1115 701 assert_nil values.detect {|value| value.custom_field == cf2}
Chris@1115 702
Chris@1115 703 issue.tracker_id = 2
Chris@1115 704 values = issue.editable_custom_field_values(user)
Chris@1115 705 assert values.detect {|value| value.custom_field == cf1}
Chris@1115 706 assert values.detect {|value| value.custom_field == cf2}
Chris@1115 707 end
Chris@1115 708
Chris@1517 709 def test_editable_custom_fields_should_return_custom_field_that_is_enabled_for_the_role_only
Chris@1517 710 enabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [1,2])
Chris@1517 711 disabled_cf = IssueCustomField.generate!(:is_for_all => true, :tracker_ids => [1], :visible => false, :role_ids => [2])
Chris@1517 712 user = User.find(2)
Chris@1517 713 issue = Issue.new(:project_id => 1, :tracker_id => 1)
Chris@1517 714
Chris@1517 715 assert_include enabled_cf, issue.editable_custom_fields(user)
Chris@1517 716 assert_not_include disabled_cf, issue.editable_custom_fields(user)
Chris@1517 717 end
Chris@1517 718
Chris@1115 719 def test_safe_attributes_should_accept_target_tracker_writable_fields
Chris@1115 720 WorkflowPermission.delete_all
Chris@1115 721 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 722 :role_id => 1, :field_name => 'due_date',
Chris@1115 723 :rule => 'readonly')
Chris@1115 724 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
Chris@1115 725 :role_id => 1, :field_name => 'start_date',
Chris@1115 726 :rule => 'readonly')
Chris@1115 727 user = User.find(2)
Chris@1115 728
Chris@1115 729 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
Chris@1115 730
Chris@1115 731 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
Chris@1115 732 'due_date' => '2012-07-14'}, user
Chris@1115 733 assert_equal Date.parse('2012-07-12'), issue.start_date
Chris@1115 734 assert_nil issue.due_date
Chris@1115 735
Chris@1115 736 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
Chris@1115 737 'due_date' => '2012-07-16',
Chris@1115 738 'tracker_id' => 2}, user
Chris@1115 739 assert_equal Date.parse('2012-07-12'), issue.start_date
Chris@1115 740 assert_equal Date.parse('2012-07-16'), issue.due_date
Chris@1115 741 end
Chris@1115 742
Chris@1115 743 def test_safe_attributes_should_accept_target_status_writable_fields
Chris@1115 744 WorkflowPermission.delete_all
Chris@1115 745 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 746 :role_id => 1, :field_name => 'due_date',
Chris@1115 747 :rule => 'readonly')
Chris@1115 748 WorkflowPermission.create!(:old_status_id => 2, :tracker_id => 1,
Chris@1115 749 :role_id => 1, :field_name => 'start_date',
Chris@1115 750 :rule => 'readonly')
Chris@1115 751 user = User.find(2)
Chris@1115 752
Chris@1115 753 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
Chris@1115 754
Chris@1115 755 issue.send :safe_attributes=, {'start_date' => '2012-07-12',
Chris@1115 756 'due_date' => '2012-07-14'},
Chris@1115 757 user
Chris@1115 758 assert_equal Date.parse('2012-07-12'), issue.start_date
Chris@1115 759 assert_nil issue.due_date
Chris@1115 760
Chris@1115 761 issue.send :safe_attributes=, {'start_date' => '2012-07-15',
Chris@1115 762 'due_date' => '2012-07-16',
Chris@1115 763 'status_id' => 2},
Chris@1115 764 user
Chris@1115 765 assert_equal Date.parse('2012-07-12'), issue.start_date
Chris@1115 766 assert_equal Date.parse('2012-07-16'), issue.due_date
Chris@1115 767 end
Chris@1115 768
Chris@1115 769 def test_required_attributes_should_be_validated
Chris@1115 770 cf = IssueCustomField.create!(:name => 'Foo', :field_format => 'string',
Chris@1115 771 :is_for_all => true, :tracker_ids => [1, 2])
Chris@1115 772
Chris@1115 773 WorkflowPermission.delete_all
Chris@1115 774 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 775 :role_id => 1, :field_name => 'due_date',
Chris@1115 776 :rule => 'required')
Chris@1115 777 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 778 :role_id => 1, :field_name => 'category_id',
Chris@1115 779 :rule => 'required')
Chris@1115 780 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 781 :role_id => 1, :field_name => cf.id.to_s,
Chris@1115 782 :rule => 'required')
Chris@1115 783
Chris@1115 784 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
Chris@1115 785 :role_id => 1, :field_name => 'start_date',
Chris@1115 786 :rule => 'required')
Chris@1115 787 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 2,
Chris@1115 788 :role_id => 1, :field_name => cf.id.to_s,
Chris@1115 789 :rule => 'required')
Chris@1115 790 user = User.find(2)
Chris@1115 791
Chris@1115 792 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1115 793 :status_id => 1, :subject => 'Required fields',
Chris@1115 794 :author => user)
Chris@1115 795 assert_equal [cf.id.to_s, "category_id", "due_date"],
Chris@1115 796 issue.required_attribute_names(user).sort
Chris@1115 797 assert !issue.save, "Issue was saved"
Chris@1115 798 assert_equal ["Category can't be blank", "Due date can't be blank", "Foo can't be blank"],
Chris@1115 799 issue.errors.full_messages.sort
Chris@1115 800
Chris@1115 801 issue.tracker_id = 2
Chris@1115 802 assert_equal [cf.id.to_s, "start_date"], issue.required_attribute_names(user).sort
Chris@1115 803 assert !issue.save, "Issue was saved"
Chris@1115 804 assert_equal ["Foo can't be blank", "Start date can't be blank"],
Chris@1115 805 issue.errors.full_messages.sort
Chris@1115 806
Chris@1115 807 issue.start_date = Date.today
Chris@1115 808 issue.custom_field_values = {cf.id.to_s => 'bar'}
Chris@1115 809 assert issue.save
Chris@1115 810 end
Chris@1115 811
Chris@1115 812 def test_required_attribute_names_for_multiple_roles_should_intersect_rules
Chris@1115 813 WorkflowPermission.delete_all
Chris@1115 814 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 815 :role_id => 1, :field_name => 'due_date',
Chris@1115 816 :rule => 'required')
Chris@1115 817 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 818 :role_id => 1, :field_name => 'start_date',
Chris@1115 819 :rule => 'required')
Chris@1115 820 user = User.find(2)
Chris@1115 821 member = Member.find(1)
Chris@1115 822 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
Chris@1115 823
Chris@1115 824 assert_equal %w(due_date start_date), issue.required_attribute_names(user).sort
Chris@1115 825
Chris@1115 826 member.role_ids = [1, 2]
Chris@1115 827 member.save!
Chris@1115 828 assert_equal [], issue.required_attribute_names(user.reload)
Chris@1115 829
Chris@1115 830 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 831 :role_id => 2, :field_name => 'due_date',
Chris@1115 832 :rule => 'required')
Chris@1115 833 assert_equal %w(due_date), issue.required_attribute_names(user)
Chris@1115 834
Chris@1115 835 member.role_ids = [1, 2, 3]
Chris@1115 836 member.save!
Chris@1115 837 assert_equal [], issue.required_attribute_names(user.reload)
Chris@1115 838
Chris@1115 839 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 840 :role_id => 2, :field_name => 'due_date',
Chris@1115 841 :rule => 'readonly')
Chris@1115 842 # required + readonly => required
Chris@1115 843 assert_equal %w(due_date), issue.required_attribute_names(user)
Chris@1115 844 end
Chris@1115 845
Chris@1115 846 def test_read_only_attribute_names_for_multiple_roles_should_intersect_rules
Chris@1115 847 WorkflowPermission.delete_all
Chris@1115 848 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 849 :role_id => 1, :field_name => 'due_date',
Chris@1115 850 :rule => 'readonly')
Chris@1115 851 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 852 :role_id => 1, :field_name => 'start_date',
Chris@1115 853 :rule => 'readonly')
Chris@1115 854 user = User.find(2)
Chris@1115 855 member = Member.find(1)
Chris@1115 856 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1)
Chris@1115 857
Chris@1115 858 assert_equal %w(due_date start_date), issue.read_only_attribute_names(user).sort
Chris@1115 859
Chris@1115 860 member.role_ids = [1, 2]
Chris@1115 861 member.save!
Chris@1115 862 assert_equal [], issue.read_only_attribute_names(user.reload)
Chris@1115 863
Chris@1115 864 WorkflowPermission.create!(:old_status_id => 1, :tracker_id => 1,
Chris@1115 865 :role_id => 2, :field_name => 'due_date',
Chris@1115 866 :rule => 'readonly')
Chris@1115 867 assert_equal %w(due_date), issue.read_only_attribute_names(user)
Chris@1115 868 end
Chris@1115 869
Chris@0 870 def test_copy
Chris@0 871 issue = Issue.new.copy_from(1)
Chris@1115 872 assert issue.copy?
Chris@0 873 assert issue.save
Chris@0 874 issue.reload
Chris@0 875 orig = Issue.find(1)
Chris@0 876 assert_equal orig.subject, issue.subject
Chris@0 877 assert_equal orig.tracker, issue.tracker
Chris@0 878 assert_equal "125", issue.custom_value_for(2).value
Chris@0 879 end
Chris@0 880
Chris@0 881 def test_copy_should_copy_status
Chris@0 882 orig = Issue.find(8)
Chris@0 883 assert orig.status != IssueStatus.default
Chris@441 884
Chris@0 885 issue = Issue.new.copy_from(orig)
Chris@0 886 assert issue.save
Chris@0 887 issue.reload
Chris@0 888 assert_equal orig.status, issue.status
Chris@0 889 end
Chris@441 890
Chris@1115 891 def test_copy_should_add_relation_with_copied_issue
Chris@1115 892 copied = Issue.find(1)
Chris@1115 893 issue = Issue.new.copy_from(copied)
Chris@1115 894 assert issue.save
Chris@1115 895 issue.reload
Chris@1115 896
Chris@1115 897 assert_equal 1, issue.relations.size
Chris@1115 898 relation = issue.relations.first
Chris@1115 899 assert_equal 'copied_to', relation.relation_type
Chris@1115 900 assert_equal copied, relation.issue_from
Chris@1115 901 assert_equal issue, relation.issue_to
Chris@1115 902 end
Chris@1115 903
Chris@1115 904 def test_copy_should_copy_subtasks
Chris@1115 905 issue = Issue.generate_with_descendants!
Chris@1115 906
Chris@1115 907 copy = issue.reload.copy
Chris@1115 908 copy.author = User.find(7)
Chris@1115 909 assert_difference 'Issue.count', 1+issue.descendants.count do
Chris@1115 910 assert copy.save
Chris@1115 911 end
Chris@1115 912 copy.reload
Chris@1115 913 assert_equal %w(Child1 Child2), copy.children.map(&:subject).sort
Chris@1115 914 child_copy = copy.children.detect {|c| c.subject == 'Child1'}
Chris@1115 915 assert_equal %w(Child11), child_copy.children.map(&:subject).sort
Chris@1115 916 assert_equal copy.author, child_copy.author
Chris@1115 917 end
Chris@1115 918
Chris@1464 919 def test_copy_as_a_child_of_copied_issue_should_not_copy_itself
Chris@1464 920 parent = Issue.generate!
Chris@1464 921 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
Chris@1464 922 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
Chris@1464 923
Chris@1464 924 copy = parent.reload.copy
Chris@1464 925 copy.parent_issue_id = parent.id
Chris@1464 926 copy.author = User.find(7)
Chris@1464 927 assert_difference 'Issue.count', 3 do
Chris@1464 928 assert copy.save
Chris@1464 929 end
Chris@1464 930 parent.reload
Chris@1464 931 copy.reload
Chris@1464 932 assert_equal parent, copy.parent
Chris@1464 933 assert_equal 3, parent.children.count
Chris@1464 934 assert_equal 5, parent.descendants.count
Chris@1464 935 assert_equal 2, copy.children.count
Chris@1464 936 assert_equal 2, copy.descendants.count
Chris@1464 937 end
Chris@1464 938
Chris@1464 939 def test_copy_as_a_descendant_of_copied_issue_should_not_copy_itself
Chris@1464 940 parent = Issue.generate!
Chris@1464 941 child1 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 1')
Chris@1464 942 child2 = Issue.generate!(:parent_issue_id => parent.id, :subject => 'Child 2')
Chris@1464 943
Chris@1464 944 copy = parent.reload.copy
Chris@1464 945 copy.parent_issue_id = child1.id
Chris@1464 946 copy.author = User.find(7)
Chris@1464 947 assert_difference 'Issue.count', 3 do
Chris@1464 948 assert copy.save
Chris@1464 949 end
Chris@1464 950 parent.reload
Chris@1464 951 child1.reload
Chris@1464 952 copy.reload
Chris@1464 953 assert_equal child1, copy.parent
Chris@1464 954 assert_equal 2, parent.children.count
Chris@1464 955 assert_equal 5, parent.descendants.count
Chris@1464 956 assert_equal 1, child1.children.count
Chris@1464 957 assert_equal 3, child1.descendants.count
Chris@1464 958 assert_equal 2, copy.children.count
Chris@1464 959 assert_equal 2, copy.descendants.count
Chris@1464 960 end
Chris@1464 961
Chris@1115 962 def test_copy_should_copy_subtasks_to_target_project
Chris@1115 963 issue = Issue.generate_with_descendants!
Chris@1115 964
Chris@1115 965 copy = issue.copy(:project_id => 3)
Chris@1115 966 assert_difference 'Issue.count', 1+issue.descendants.count do
Chris@1115 967 assert copy.save
Chris@1115 968 end
Chris@1115 969 assert_equal [3], copy.reload.descendants.map(&:project_id).uniq
Chris@1115 970 end
Chris@1115 971
Chris@1115 972 def test_copy_should_not_copy_subtasks_twice_when_saving_twice
Chris@1115 973 issue = Issue.generate_with_descendants!
Chris@1115 974
Chris@1115 975 copy = issue.reload.copy
Chris@1115 976 assert_difference 'Issue.count', 1+issue.descendants.count do
Chris@1115 977 assert copy.save
Chris@1115 978 assert copy.save
Chris@1115 979 end
Chris@1115 980 end
Chris@1115 981
Chris@1115 982 def test_should_not_call_after_project_change_on_creation
Chris@1115 983 issue = Issue.new(:project_id => 1, :tracker_id => 1, :status_id => 1,
Chris@1115 984 :subject => 'Test', :author_id => 1)
Chris@1115 985 issue.expects(:after_project_change).never
Chris@1115 986 issue.save!
Chris@1115 987 end
Chris@1115 988
Chris@1115 989 def test_should_not_call_after_project_change_on_update
Chris@1115 990 issue = Issue.find(1)
Chris@1115 991 issue.project = Project.find(1)
Chris@1115 992 issue.subject = 'No project change'
Chris@1115 993 issue.expects(:after_project_change).never
Chris@1115 994 issue.save!
Chris@1115 995 end
Chris@1115 996
Chris@1115 997 def test_should_call_after_project_change_on_project_change
Chris@1115 998 issue = Issue.find(1)
Chris@1115 999 issue.project = Project.find(2)
Chris@1115 1000 issue.expects(:after_project_change).once
Chris@1115 1001 issue.save!
Chris@1115 1002 end
Chris@1115 1003
Chris@1115 1004 def test_adding_journal_should_update_timestamp
Chris@1115 1005 issue = Issue.find(1)
Chris@1115 1006 updated_on_was = issue.updated_on
Chris@1115 1007
Chris@1115 1008 issue.init_journal(User.first, "Adding notes")
Chris@1115 1009 assert_difference 'Journal.count' do
Chris@1115 1010 assert issue.save
Chris@1115 1011 end
Chris@1115 1012 issue.reload
Chris@1115 1013
Chris@1115 1014 assert_not_equal updated_on_was, issue.updated_on
Chris@1115 1015 end
Chris@1115 1016
Chris@0 1017 def test_should_close_duplicates
Chris@0 1018 # Create 3 issues
Chris@1115 1019 issue1 = Issue.generate!
Chris@1115 1020 issue2 = Issue.generate!
Chris@1115 1021 issue3 = Issue.generate!
Chris@441 1022
Chris@0 1023 # 2 is a dupe of 1
Chris@1115 1024 IssueRelation.create!(:issue_from => issue2, :issue_to => issue1,
Chris@1115 1025 :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@0 1026 # And 3 is a dupe of 2
Chris@1115 1027 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
Chris@1115 1028 :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@0 1029 # And 3 is a dupe of 1 (circular duplicates)
Chris@1115 1030 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1,
Chris@1115 1031 :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@441 1032
Chris@0 1033 assert issue1.reload.duplicates.include?(issue2)
Chris@441 1034
Chris@0 1035 # Closing issue 1
Chris@1464 1036 issue1.init_journal(User.first, "Closing issue1")
Chris@1464 1037 issue1.status = IssueStatus.where(:is_closed => true).first
Chris@0 1038 assert issue1.save
Chris@0 1039 # 2 and 3 should be also closed
Chris@0 1040 assert issue2.reload.closed?
Chris@441 1041 assert issue3.reload.closed?
Chris@0 1042 end
Chris@441 1043
Chris@0 1044 def test_should_not_close_duplicated_issue
Chris@1115 1045 issue1 = Issue.generate!
Chris@1115 1046 issue2 = Issue.generate!
Chris@441 1047
Chris@0 1048 # 2 is a dupe of 1
Chris@1115 1049 IssueRelation.create(:issue_from => issue2, :issue_to => issue1,
Chris@1115 1050 :relation_type => IssueRelation::TYPE_DUPLICATES)
Chris@0 1051 # 2 is a dup of 1 but 1 is not a duplicate of 2
Chris@0 1052 assert !issue2.reload.duplicates.include?(issue1)
Chris@441 1053
Chris@0 1054 # Closing issue 2
Chris@1464 1055 issue2.init_journal(User.first, "Closing issue2")
Chris@1464 1056 issue2.status = IssueStatus.where(:is_closed => true).first
Chris@0 1057 assert issue2.save
Chris@0 1058 # 1 should not be also closed
Chris@0 1059 assert !issue1.reload.closed?
Chris@0 1060 end
Chris@441 1061
Chris@0 1062 def test_assignable_versions
Chris@1115 1063 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@1115 1064 :status_id => 1, :fixed_version_id => 1,
Chris@1115 1065 :subject => 'New issue')
Chris@0 1066 assert_equal ['open'], issue.assignable_versions.collect(&:status).uniq
Chris@0 1067 end
Chris@441 1068
Chris@0 1069 def test_should_not_be_able_to_assign_a_new_issue_to_a_closed_version
Chris@1115 1070 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@1115 1071 :status_id => 1, :fixed_version_id => 1,
Chris@1115 1072 :subject => 'New issue')
Chris@0 1073 assert !issue.save
Chris@1464 1074 assert_not_equal [], issue.errors[:fixed_version_id]
Chris@0 1075 end
Chris@441 1076
Chris@0 1077 def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
Chris@1115 1078 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@1115 1079 :status_id => 1, :fixed_version_id => 2,
Chris@1115 1080 :subject => 'New issue')
Chris@0 1081 assert !issue.save
Chris@1464 1082 assert_not_equal [], issue.errors[:fixed_version_id]
Chris@0 1083 end
Chris@441 1084
Chris@0 1085 def test_should_be_able_to_assign_a_new_issue_to_an_open_version
Chris@1115 1086 issue = Issue.new(:project_id => 1, :tracker_id => 1, :author_id => 1,
Chris@1115 1087 :status_id => 1, :fixed_version_id => 3,
Chris@1115 1088 :subject => 'New issue')
Chris@0 1089 assert issue.save
Chris@0 1090 end
Chris@441 1091
Chris@0 1092 def test_should_be_able_to_update_an_issue_assigned_to_a_closed_version
Chris@0 1093 issue = Issue.find(11)
Chris@0 1094 assert_equal 'closed', issue.fixed_version.status
Chris@0 1095 issue.subject = 'Subject changed'
Chris@0 1096 assert issue.save
Chris@0 1097 end
Chris@441 1098
Chris@0 1099 def test_should_not_be_able_to_reopen_an_issue_assigned_to_a_closed_version
Chris@0 1100 issue = Issue.find(11)
Chris@0 1101 issue.status_id = 1
Chris@0 1102 assert !issue.save
Chris@1464 1103 assert_not_equal [], issue.errors[:base]
Chris@0 1104 end
Chris@441 1105
Chris@0 1106 def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
Chris@0 1107 issue = Issue.find(11)
Chris@0 1108 issue.status_id = 1
Chris@0 1109 issue.fixed_version_id = 3
Chris@0 1110 assert issue.save
Chris@0 1111 end
Chris@441 1112
Chris@0 1113 def test_should_be_able_to_reopen_an_issue_assigned_to_a_locked_version
Chris@0 1114 issue = Issue.find(12)
Chris@0 1115 assert_equal 'locked', issue.fixed_version.status
Chris@0 1116 issue.status_id = 1
Chris@0 1117 assert issue.save
Chris@0 1118 end
Chris@441 1119
Chris@1115 1120 def test_should_not_be_able_to_keep_unshared_version_when_changing_project
Chris@1115 1121 issue = Issue.find(2)
Chris@1115 1122 assert_equal 2, issue.fixed_version_id
Chris@1115 1123 issue.project_id = 3
Chris@1115 1124 assert_nil issue.fixed_version_id
Chris@1115 1125 issue.fixed_version_id = 2
Chris@1115 1126 assert !issue.save
Chris@1115 1127 assert_include 'Target version is not included in the list', issue.errors.full_messages
Chris@1115 1128 end
Chris@1115 1129
Chris@1115 1130 def test_should_keep_shared_version_when_changing_project
Chris@1115 1131 Version.find(2).update_attribute :sharing, 'tree'
Chris@1464 1132
Chris@1115 1133 issue = Issue.find(2)
Chris@1115 1134 assert_equal 2, issue.fixed_version_id
Chris@1115 1135 issue.project_id = 3
Chris@1115 1136 assert_equal 2, issue.fixed_version_id
Chris@1115 1137 assert issue.save
Chris@1115 1138 end
Chris@1115 1139
Chris@1115 1140 def test_allowed_target_projects_on_move_should_include_projects_with_issue_tracking_enabled
Chris@1115 1141 assert_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
Chris@1115 1142 end
Chris@1115 1143
Chris@1115 1144 def test_allowed_target_projects_on_move_should_not_include_projects_with_issue_tracking_disabled
Chris@1115 1145 Project.find(2).disable_module! :issue_tracking
Chris@1115 1146 assert_not_include Project.find(2), Issue.allowed_target_projects_on_move(User.find(2))
Chris@1115 1147 end
Chris@1115 1148
Chris@0 1149 def test_move_to_another_project_with_same_category
Chris@0 1150 issue = Issue.find(1)
Chris@1115 1151 issue.project = Project.find(2)
Chris@1115 1152 assert issue.save
Chris@0 1153 issue.reload
Chris@0 1154 assert_equal 2, issue.project_id
Chris@0 1155 # Category changes
Chris@0 1156 assert_equal 4, issue.category_id
Chris@0 1157 # Make sure time entries were move to the target project
Chris@0 1158 assert_equal 2, issue.time_entries.first.project_id
Chris@0 1159 end
Chris@441 1160
Chris@0 1161 def test_move_to_another_project_without_same_category
Chris@0 1162 issue = Issue.find(2)
Chris@1115 1163 issue.project = Project.find(2)
Chris@1115 1164 assert issue.save
Chris@0 1165 issue.reload
Chris@0 1166 assert_equal 2, issue.project_id
Chris@0 1167 # Category cleared
Chris@0 1168 assert_nil issue.category_id
Chris@0 1169 end
Chris@441 1170
Chris@0 1171 def test_move_to_another_project_should_clear_fixed_version_when_not_shared
Chris@0 1172 issue = Issue.find(1)
Chris@0 1173 issue.update_attribute(:fixed_version_id, 1)
Chris@1115 1174 issue.project = Project.find(2)
Chris@1115 1175 assert issue.save
Chris@0 1176 issue.reload
Chris@0 1177 assert_equal 2, issue.project_id
Chris@0 1178 # Cleared fixed_version
Chris@0 1179 assert_equal nil, issue.fixed_version
Chris@0 1180 end
Chris@441 1181
Chris@0 1182 def test_move_to_another_project_should_keep_fixed_version_when_shared_with_the_target_project
Chris@0 1183 issue = Issue.find(1)
Chris@0 1184 issue.update_attribute(:fixed_version_id, 4)
Chris@1115 1185 issue.project = Project.find(5)
Chris@1115 1186 assert issue.save
Chris@0 1187 issue.reload
Chris@0 1188 assert_equal 5, issue.project_id
Chris@0 1189 # Keep fixed_version
Chris@0 1190 assert_equal 4, issue.fixed_version_id
Chris@0 1191 end
Chris@441 1192
Chris@0 1193 def test_move_to_another_project_should_clear_fixed_version_when_not_shared_with_the_target_project
Chris@0 1194 issue = Issue.find(1)
Chris@0 1195 issue.update_attribute(:fixed_version_id, 1)
Chris@1115 1196 issue.project = Project.find(5)
Chris@1115 1197 assert issue.save
Chris@0 1198 issue.reload
Chris@0 1199 assert_equal 5, issue.project_id
Chris@0 1200 # Cleared fixed_version
Chris@0 1201 assert_equal nil, issue.fixed_version
Chris@0 1202 end
Chris@441 1203
Chris@0 1204 def test_move_to_another_project_should_keep_fixed_version_when_shared_systemwide
Chris@0 1205 issue = Issue.find(1)
Chris@0 1206 issue.update_attribute(:fixed_version_id, 7)
Chris@1115 1207 issue.project = Project.find(2)
Chris@1115 1208 assert issue.save
Chris@0 1209 issue.reload
Chris@0 1210 assert_equal 2, issue.project_id
Chris@0 1211 # Keep fixed_version
Chris@0 1212 assert_equal 7, issue.fixed_version_id
Chris@0 1213 end
Chris@441 1214
Chris@1115 1215 def test_move_to_another_project_should_keep_parent_if_valid
Chris@1115 1216 issue = Issue.find(1)
Chris@1115 1217 issue.update_attribute(:parent_issue_id, 2)
Chris@1115 1218 issue.project = Project.find(3)
Chris@1115 1219 assert issue.save
Chris@1115 1220 issue.reload
Chris@1115 1221 assert_equal 2, issue.parent_id
Chris@1115 1222 end
Chris@1115 1223
Chris@1115 1224 def test_move_to_another_project_should_clear_parent_if_not_valid
Chris@1115 1225 issue = Issue.find(1)
Chris@1115 1226 issue.update_attribute(:parent_issue_id, 2)
Chris@1115 1227 issue.project = Project.find(2)
Chris@1115 1228 assert issue.save
Chris@1115 1229 issue.reload
Chris@1115 1230 assert_nil issue.parent_id
Chris@1115 1231 end
Chris@1115 1232
Chris@0 1233 def test_move_to_another_project_with_disabled_tracker
Chris@0 1234 issue = Issue.find(1)
Chris@0 1235 target = Project.find(2)
Chris@0 1236 target.tracker_ids = [3]
Chris@0 1237 target.save
Chris@1115 1238 issue.project = target
Chris@1115 1239 assert issue.save
Chris@0 1240 issue.reload
Chris@1115 1241 assert_equal 2, issue.project_id
Chris@1115 1242 assert_equal 3, issue.tracker_id
Chris@0 1243 end
Chris@441 1244
Chris@0 1245 def test_copy_to_the_same_project
Chris@0 1246 issue = Issue.find(1)
Chris@1115 1247 copy = issue.copy
Chris@0 1248 assert_difference 'Issue.count' do
Chris@1115 1249 copy.save!
Chris@0 1250 end
Chris@0 1251 assert_kind_of Issue, copy
Chris@0 1252 assert_equal issue.project, copy.project
Chris@0 1253 assert_equal "125", copy.custom_value_for(2).value
Chris@0 1254 end
Chris@441 1255
Chris@0 1256 def test_copy_to_another_project_and_tracker
Chris@0 1257 issue = Issue.find(1)
Chris@1115 1258 copy = issue.copy(:project_id => 3, :tracker_id => 2)
Chris@0 1259 assert_difference 'Issue.count' do
Chris@1115 1260 copy.save!
Chris@0 1261 end
Chris@0 1262 copy.reload
Chris@0 1263 assert_kind_of Issue, copy
Chris@0 1264 assert_equal Project.find(3), copy.project
Chris@0 1265 assert_equal Tracker.find(2), copy.tracker
Chris@0 1266 # Custom field #2 is not associated with target tracker
Chris@0 1267 assert_nil copy.custom_value_for(2)
Chris@0 1268 end
Chris@0 1269
Chris@1464 1270 test "#copy should not create a journal" do
Chris@1464 1271 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
Chris@1464 1272 copy.save!
Chris@1464 1273 assert_equal 0, copy.reload.journals.size
Chris@1464 1274 end
Chris@0 1275
Chris@1464 1276 test "#copy should allow assigned_to changes" do
Chris@1464 1277 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :assigned_to_id => 3)
Chris@1464 1278 assert_equal 3, copy.assigned_to_id
Chris@1464 1279 end
Chris@441 1280
Chris@1464 1281 test "#copy should allow status changes" do
Chris@1464 1282 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :status_id => 2)
Chris@1464 1283 assert_equal 2, copy.status_id
Chris@1464 1284 end
Chris@0 1285
Chris@1464 1286 test "#copy should allow start date changes" do
Chris@1464 1287 date = Date.today
Chris@1464 1288 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
Chris@1464 1289 assert_equal date, copy.start_date
Chris@1464 1290 end
Chris@0 1291
Chris@1464 1292 test "#copy should allow due date changes" do
Chris@1464 1293 date = Date.today
Chris@1464 1294 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :due_date => date)
Chris@1464 1295 assert_equal date, copy.due_date
Chris@1464 1296 end
Chris@0 1297
Chris@1464 1298 test "#copy should set current user as author" do
Chris@1464 1299 User.current = User.find(9)
Chris@1464 1300 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2)
Chris@1464 1301 assert_equal User.current, copy.author
Chris@1464 1302 end
Chris@0 1303
Chris@1464 1304 test "#copy should create a journal with notes" do
Chris@1464 1305 date = Date.today
Chris@1464 1306 notes = "Notes added when copying"
Chris@1464 1307 copy = Issue.find(1).copy(:project_id => 3, :tracker_id => 2, :start_date => date)
Chris@1464 1308 copy.init_journal(User.current, notes)
Chris@1464 1309 copy.save!
Chris@441 1310
Chris@1464 1311 assert_equal 1, copy.journals.size
Chris@1464 1312 journal = copy.journals.first
Chris@1464 1313 assert_equal 0, journal.details.size
Chris@1464 1314 assert_equal notes, journal.notes
Chris@1115 1315 end
Chris@441 1316
Chris@1115 1317 def test_valid_parent_project
Chris@1115 1318 issue = Issue.find(1)
Chris@1115 1319 issue_in_same_project = Issue.find(2)
Chris@1115 1320 issue_in_child_project = Issue.find(5)
Chris@1115 1321 issue_in_grandchild_project = Issue.generate!(:project_id => 6, :tracker_id => 1)
Chris@1115 1322 issue_in_other_child_project = Issue.find(6)
Chris@1115 1323 issue_in_different_tree = Issue.find(4)
Chris@441 1324
Chris@1115 1325 with_settings :cross_project_subtasks => '' do
Chris@1115 1326 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
Chris@1115 1327 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
Chris@1115 1328 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
Chris@1115 1329 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
Chris@0 1330 end
Chris@1115 1331
Chris@1115 1332 with_settings :cross_project_subtasks => 'system' do
Chris@1115 1333 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
Chris@1115 1334 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
Chris@1115 1335 assert_equal true, issue.valid_parent_project?(issue_in_different_tree)
Chris@1115 1336 end
Chris@1115 1337
Chris@1115 1338 with_settings :cross_project_subtasks => 'tree' do
Chris@1115 1339 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
Chris@1115 1340 assert_equal true, issue.valid_parent_project?(issue_in_child_project)
Chris@1115 1341 assert_equal true, issue.valid_parent_project?(issue_in_grandchild_project)
Chris@1115 1342 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
Chris@1115 1343
Chris@1115 1344 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_same_project)
Chris@1115 1345 assert_equal true, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
Chris@1115 1346 end
Chris@1115 1347
Chris@1115 1348 with_settings :cross_project_subtasks => 'descendants' do
Chris@1115 1349 assert_equal true, issue.valid_parent_project?(issue_in_same_project)
Chris@1115 1350 assert_equal false, issue.valid_parent_project?(issue_in_child_project)
Chris@1115 1351 assert_equal false, issue.valid_parent_project?(issue_in_grandchild_project)
Chris@1115 1352 assert_equal false, issue.valid_parent_project?(issue_in_different_tree)
Chris@1115 1353
Chris@1115 1354 assert_equal true, issue_in_child_project.valid_parent_project?(issue)
Chris@1115 1355 assert_equal false, issue_in_child_project.valid_parent_project?(issue_in_other_child_project)
Chris@1115 1356 end
Chris@1115 1357 end
Chris@1115 1358
Chris@1115 1359 def test_recipients_should_include_previous_assignee
Chris@1115 1360 user = User.find(3)
Chris@1115 1361 user.members.update_all ["mail_notification = ?", false]
Chris@1115 1362 user.update_attribute :mail_notification, 'only_assigned'
Chris@1115 1363
Chris@1115 1364 issue = Issue.find(2)
Chris@1115 1365 issue.assigned_to = nil
Chris@1115 1366 assert_include user.mail, issue.recipients
Chris@1115 1367 issue.save!
Chris@1115 1368 assert !issue.recipients.include?(user.mail)
Chris@0 1369 end
Chris@441 1370
Chris@0 1371 def test_recipients_should_not_include_users_that_cannot_view_the_issue
Chris@0 1372 issue = Issue.find(12)
Chris@0 1373 assert issue.recipients.include?(issue.author.mail)
Chris@1115 1374 # copy the issue to a private project
Chris@1115 1375 copy = issue.copy(:project_id => 5, :tracker_id => 2)
Chris@0 1376 # author is not a member of project anymore
Chris@0 1377 assert !copy.recipients.include?(copy.author.mail)
Chris@0 1378 end
Chris@0 1379
Chris@909 1380 def test_recipients_should_include_the_assigned_group_members
Chris@1115 1381 group_member = User.generate!
Chris@909 1382 group = Group.generate!
Chris@909 1383 group.users << group_member
Chris@909 1384
Chris@909 1385 issue = Issue.find(12)
Chris@909 1386 issue.assigned_to = group
Chris@909 1387 assert issue.recipients.include?(group_member.mail)
Chris@909 1388 end
Chris@909 1389
Chris@0 1390 def test_watcher_recipients_should_not_include_users_that_cannot_view_the_issue
Chris@0 1391 user = User.find(3)
Chris@0 1392 issue = Issue.find(9)
Chris@0 1393 Watcher.create!(:user => user, :watchable => issue)
Chris@0 1394 assert issue.watched_by?(user)
Chris@0 1395 assert !issue.watcher_recipients.include?(user.mail)
Chris@0 1396 end
Chris@441 1397
Chris@0 1398 def test_issue_destroy
Chris@0 1399 Issue.find(1).destroy
Chris@0 1400 assert_nil Issue.find_by_id(1)
Chris@0 1401 assert_nil TimeEntry.find_by_issue_id(1)
Chris@0 1402 end
Chris@441 1403
Chris@1517 1404 def test_destroy_should_delete_time_entries_custom_values
Chris@1517 1405 issue = Issue.generate!
Chris@1517 1406 time_entry = TimeEntry.generate!(:issue => issue, :custom_field_values => {10 => '1'})
Chris@1517 1407
Chris@1517 1408 assert_difference 'CustomValue.where(:customized_type => "TimeEntry").count', -1 do
Chris@1517 1409 assert issue.destroy
Chris@1517 1410 end
Chris@1517 1411 end
Chris@1517 1412
Chris@1115 1413 def test_destroying_a_deleted_issue_should_not_raise_an_error
Chris@1115 1414 issue = Issue.find(1)
Chris@1115 1415 Issue.find(1).destroy
Chris@1115 1416
Chris@1115 1417 assert_nothing_raised do
Chris@1115 1418 assert_no_difference 'Issue.count' do
Chris@1115 1419 issue.destroy
Chris@1115 1420 end
Chris@1115 1421 assert issue.destroyed?
Chris@1115 1422 end
Chris@1115 1423 end
Chris@1115 1424
Chris@1115 1425 def test_destroying_a_stale_issue_should_not_raise_an_error
Chris@1115 1426 issue = Issue.find(1)
Chris@1115 1427 Issue.find(1).update_attribute :subject, "Updated"
Chris@1115 1428
Chris@1115 1429 assert_nothing_raised do
Chris@1115 1430 assert_difference 'Issue.count', -1 do
Chris@1115 1431 issue.destroy
Chris@1115 1432 end
Chris@1115 1433 assert issue.destroyed?
Chris@1115 1434 end
Chris@1115 1435 end
Chris@1115 1436
Chris@0 1437 def test_blocked
Chris@0 1438 blocked_issue = Issue.find(9)
Chris@0 1439 blocking_issue = Issue.find(10)
Chris@441 1440
Chris@0 1441 assert blocked_issue.blocked?
Chris@0 1442 assert !blocking_issue.blocked?
Chris@0 1443 end
Chris@441 1444
Chris@0 1445 def test_blocked_issues_dont_allow_closed_statuses
Chris@0 1446 blocked_issue = Issue.find(9)
Chris@441 1447
Chris@0 1448 allowed_statuses = blocked_issue.new_statuses_allowed_to(users(:users_002))
Chris@0 1449 assert !allowed_statuses.empty?
Chris@0 1450 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
Chris@0 1451 assert closed_statuses.empty?
Chris@0 1452 end
Chris@441 1453
Chris@0 1454 def test_unblocked_issues_allow_closed_statuses
Chris@0 1455 blocking_issue = Issue.find(10)
Chris@441 1456
Chris@0 1457 allowed_statuses = blocking_issue.new_statuses_allowed_to(users(:users_002))
Chris@0 1458 assert !allowed_statuses.empty?
Chris@0 1459 closed_statuses = allowed_statuses.select {|st| st.is_closed?}
Chris@0 1460 assert !closed_statuses.empty?
Chris@0 1461 end
Chris@441 1462
Chris@1115 1463 def test_reschedule_an_issue_without_dates
Chris@1115 1464 with_settings :non_working_week_days => [] do
Chris@1115 1465 issue = Issue.new(:start_date => nil, :due_date => nil)
Chris@1115 1466 issue.reschedule_on '2012-10-09'.to_date
Chris@1115 1467 assert_equal '2012-10-09'.to_date, issue.start_date
Chris@1115 1468 assert_equal '2012-10-09'.to_date, issue.due_date
Chris@1115 1469 end
Chris@441 1470
Chris@1115 1471 with_settings :non_working_week_days => %w(6 7) do
Chris@1115 1472 issue = Issue.new(:start_date => nil, :due_date => nil)
Chris@1115 1473 issue.reschedule_on '2012-10-09'.to_date
Chris@1115 1474 assert_equal '2012-10-09'.to_date, issue.start_date
Chris@1115 1475 assert_equal '2012-10-09'.to_date, issue.due_date
Chris@1115 1476
Chris@1115 1477 issue = Issue.new(:start_date => nil, :due_date => nil)
Chris@1115 1478 issue.reschedule_on '2012-10-13'.to_date
Chris@1115 1479 assert_equal '2012-10-15'.to_date, issue.start_date
Chris@1115 1480 assert_equal '2012-10-15'.to_date, issue.due_date
Chris@1115 1481 end
Chris@1115 1482 end
Chris@1115 1483
Chris@1115 1484 def test_reschedule_an_issue_with_start_date
Chris@1115 1485 with_settings :non_working_week_days => [] do
Chris@1115 1486 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
Chris@1115 1487 issue.reschedule_on '2012-10-13'.to_date
Chris@1115 1488 assert_equal '2012-10-13'.to_date, issue.start_date
Chris@1115 1489 assert_equal '2012-10-13'.to_date, issue.due_date
Chris@1115 1490 end
Chris@1115 1491
Chris@1115 1492 with_settings :non_working_week_days => %w(6 7) do
Chris@1115 1493 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
Chris@1115 1494 issue.reschedule_on '2012-10-11'.to_date
Chris@1115 1495 assert_equal '2012-10-11'.to_date, issue.start_date
Chris@1115 1496 assert_equal '2012-10-11'.to_date, issue.due_date
Chris@1115 1497
Chris@1115 1498 issue = Issue.new(:start_date => '2012-10-09', :due_date => nil)
Chris@1115 1499 issue.reschedule_on '2012-10-13'.to_date
Chris@1115 1500 assert_equal '2012-10-15'.to_date, issue.start_date
Chris@1115 1501 assert_equal '2012-10-15'.to_date, issue.due_date
Chris@1115 1502 end
Chris@1115 1503 end
Chris@1115 1504
Chris@1115 1505 def test_reschedule_an_issue_with_start_and_due_dates
Chris@1115 1506 with_settings :non_working_week_days => [] do
Chris@1115 1507 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-15')
Chris@1115 1508 issue.reschedule_on '2012-10-13'.to_date
Chris@1115 1509 assert_equal '2012-10-13'.to_date, issue.start_date
Chris@1115 1510 assert_equal '2012-10-19'.to_date, issue.due_date
Chris@1115 1511 end
Chris@1115 1512
Chris@1115 1513 with_settings :non_working_week_days => %w(6 7) do
Chris@1115 1514 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19') # 8 working days
Chris@1115 1515 issue.reschedule_on '2012-10-11'.to_date
Chris@1115 1516 assert_equal '2012-10-11'.to_date, issue.start_date
Chris@1115 1517 assert_equal '2012-10-23'.to_date, issue.due_date
Chris@1115 1518
Chris@1115 1519 issue = Issue.new(:start_date => '2012-10-09', :due_date => '2012-10-19')
Chris@1115 1520 issue.reschedule_on '2012-10-13'.to_date
Chris@1115 1521 assert_equal '2012-10-15'.to_date, issue.start_date
Chris@1115 1522 assert_equal '2012-10-25'.to_date, issue.due_date
Chris@1115 1523 end
Chris@1115 1524 end
Chris@1115 1525
Chris@1115 1526 def test_rescheduling_an_issue_to_a_later_due_date_should_reschedule_following_issue
Chris@1115 1527 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1115 1528 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1115 1529 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
Chris@1115 1530 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1115 1531 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
Chris@1115 1532
Chris@1464 1533 issue1.reload
Chris@1115 1534 issue1.due_date = '2012-10-23'
chris@37 1535 issue1.save!
Chris@1115 1536 issue2.reload
Chris@1115 1537 assert_equal Date.parse('2012-10-24'), issue2.start_date
Chris@1115 1538 assert_equal Date.parse('2012-10-26'), issue2.due_date
Chris@1115 1539 end
Chris@1115 1540
Chris@1115 1541 def test_rescheduling_an_issue_to_an_earlier_due_date_should_reschedule_following_issue
Chris@1115 1542 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1115 1543 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1115 1544 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
Chris@1115 1545 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1115 1546 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
Chris@1115 1547
Chris@1464 1548 issue1.reload
Chris@1115 1549 issue1.start_date = '2012-09-17'
Chris@1115 1550 issue1.due_date = '2012-09-18'
Chris@1115 1551 issue1.save!
Chris@1115 1552 issue2.reload
Chris@1115 1553 assert_equal Date.parse('2012-09-19'), issue2.start_date
Chris@1115 1554 assert_equal Date.parse('2012-09-21'), issue2.due_date
Chris@1115 1555 end
Chris@1115 1556
Chris@1115 1557 def test_rescheduling_reschedule_following_issue_earlier_should_consider_other_preceding_issues
Chris@1115 1558 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1115 1559 issue2 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1115 1560 issue3 = Issue.generate!(:start_date => '2012-10-01', :due_date => '2012-10-02')
Chris@1115 1561 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
Chris@1115 1562 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1115 1563 IssueRelation.create!(:issue_from => issue3, :issue_to => issue2,
Chris@1115 1564 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1115 1565 assert_equal Date.parse('2012-10-18'), issue2.reload.start_date
Chris@1115 1566
Chris@1464 1567 issue1.reload
Chris@1115 1568 issue1.start_date = '2012-09-17'
Chris@1115 1569 issue1.due_date = '2012-09-18'
Chris@1115 1570 issue1.save!
Chris@1115 1571 issue2.reload
Chris@1115 1572 # Issue 2 must start after Issue 3
Chris@1115 1573 assert_equal Date.parse('2012-10-03'), issue2.start_date
Chris@1115 1574 assert_equal Date.parse('2012-10-05'), issue2.due_date
Chris@1115 1575 end
Chris@1115 1576
Chris@1115 1577 def test_rescheduling_a_stale_issue_should_not_raise_an_error
Chris@1115 1578 with_settings :non_working_week_days => [] do
Chris@1115 1579 stale = Issue.find(1)
Chris@1115 1580 issue = Issue.find(1)
Chris@1115 1581 issue.subject = "Updated"
Chris@1115 1582 issue.save!
Chris@1115 1583 date = 10.days.from_now.to_date
Chris@1115 1584 assert_nothing_raised do
Chris@1115 1585 stale.reschedule_on!(date)
Chris@1115 1586 end
Chris@1115 1587 assert_equal date, stale.reload.start_date
Chris@1115 1588 end
chris@37 1589 end
Chris@441 1590
Chris@1464 1591 def test_child_issue_should_consider_parent_soonest_start_on_create
Chris@1464 1592 set_language_if_valid 'en'
Chris@1464 1593 issue1 = Issue.generate!(:start_date => '2012-10-15', :due_date => '2012-10-17')
Chris@1464 1594 issue2 = Issue.generate!(:start_date => '2012-10-18', :due_date => '2012-10-20')
Chris@1464 1595 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2,
Chris@1464 1596 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1464 1597 issue1.reload
Chris@1464 1598 issue2.reload
Chris@1464 1599 assert_equal Date.parse('2012-10-18'), issue2.start_date
Chris@1464 1600
Chris@1464 1601 child = Issue.new(:parent_issue_id => issue2.id, :start_date => '2012-10-16',
Chris@1464 1602 :project_id => 1, :tracker_id => 1, :status_id => 1, :subject => 'Child', :author_id => 1)
Chris@1464 1603 assert !child.valid?
Chris@1464 1604 assert_include 'Start date cannot be earlier than 10/18/2012 because of preceding issues', child.errors.full_messages
Chris@1464 1605 assert_equal Date.parse('2012-10-18'), child.soonest_start
Chris@1464 1606 child.start_date = '2012-10-18'
Chris@1464 1607 assert child.save
Chris@1464 1608 end
Chris@1464 1609
Chris@1464 1610 def test_setting_parent_to_a_dependent_issue_should_not_validate
Chris@1464 1611 set_language_if_valid 'en'
Chris@1464 1612 issue1 = Issue.generate!
Chris@1464 1613 issue2 = Issue.generate!
Chris@1464 1614 issue3 = Issue.generate!
Chris@1464 1615 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1464 1616 IssueRelation.create!(:issue_from => issue3, :issue_to => issue1, :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1464 1617 issue3.reload
Chris@1464 1618 issue3.parent_issue_id = issue2.id
Chris@1464 1619 assert !issue3.valid?
Chris@1464 1620 assert_include 'Parent task is invalid', issue3.errors.full_messages
Chris@1464 1621 end
Chris@1464 1622
Chris@1464 1623 def test_setting_parent_should_not_allow_circular_dependency
Chris@1464 1624 set_language_if_valid 'en'
Chris@1464 1625 issue1 = Issue.generate!
Chris@1464 1626 issue2 = Issue.generate!
Chris@1464 1627 IssueRelation.create!(:issue_from => issue1, :issue_to => issue2, :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1464 1628 issue3 = Issue.generate!
Chris@1464 1629 issue2.reload
Chris@1464 1630 issue2.parent_issue_id = issue3.id
Chris@1464 1631 issue2.save!
Chris@1464 1632 issue4 = Issue.generate!
Chris@1464 1633 IssueRelation.create!(:issue_from => issue3, :issue_to => issue4, :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1464 1634 issue4.reload
Chris@1464 1635 issue4.parent_issue_id = issue1.id
Chris@1464 1636 assert !issue4.valid?
Chris@1464 1637 assert_include 'Parent task is invalid', issue4.errors.full_messages
Chris@1464 1638 end
Chris@1464 1639
Chris@0 1640 def test_overdue
Chris@0 1641 assert Issue.new(:due_date => 1.day.ago.to_date).overdue?
Chris@0 1642 assert !Issue.new(:due_date => Date.today).overdue?
Chris@0 1643 assert !Issue.new(:due_date => 1.day.from_now.to_date).overdue?
Chris@0 1644 assert !Issue.new(:due_date => nil).overdue?
Chris@1115 1645 assert !Issue.new(:due_date => 1.day.ago.to_date,
Chris@1464 1646 :status => IssueStatus.where(:is_closed => true).first
Chris@1115 1647 ).overdue?
Chris@0 1648 end
chris@22 1649
Chris@1464 1650 test "#behind_schedule? should be false if the issue has no start_date" do
Chris@1464 1651 assert !Issue.new(:start_date => nil,
Chris@1464 1652 :due_date => 1.day.from_now.to_date,
Chris@1464 1653 :done_ratio => 0).behind_schedule?
Chris@1464 1654 end
chris@22 1655
Chris@1464 1656 test "#behind_schedule? should be false if the issue has no end_date" do
Chris@1464 1657 assert !Issue.new(:start_date => 1.day.from_now.to_date,
Chris@1464 1658 :due_date => nil,
Chris@1464 1659 :done_ratio => 0).behind_schedule?
Chris@1464 1660 end
chris@22 1661
Chris@1464 1662 test "#behind_schedule? should be false if the issue has more done than it's calendar time" do
Chris@1464 1663 assert !Issue.new(:start_date => 50.days.ago.to_date,
Chris@1464 1664 :due_date => 50.days.from_now.to_date,
Chris@1464 1665 :done_ratio => 90).behind_schedule?
Chris@1464 1666 end
chris@22 1667
Chris@1464 1668 test "#behind_schedule? should be true if the issue hasn't been started at all" do
Chris@1464 1669 assert Issue.new(:start_date => 1.day.ago.to_date,
Chris@1464 1670 :due_date => 1.day.from_now.to_date,
Chris@1464 1671 :done_ratio => 0).behind_schedule?
Chris@1464 1672 end
chris@22 1673
Chris@1464 1674 test "#behind_schedule? should be true if the issue has used more calendar time than it's done ratio" do
Chris@1464 1675 assert Issue.new(:start_date => 100.days.ago.to_date,
Chris@1464 1676 :due_date => Date.today,
Chris@1464 1677 :done_ratio => 90).behind_schedule?
Chris@1464 1678 end
Chris@1464 1679
Chris@1464 1680 test "#assignable_users should be Users" do
Chris@1464 1681 assert_kind_of User, Issue.find(1).assignable_users.first
Chris@1464 1682 end
Chris@1464 1683
Chris@1464 1684 test "#assignable_users should include the issue author" do
Chris@1464 1685 non_project_member = User.generate!
Chris@1464 1686 issue = Issue.generate!(:author => non_project_member)
Chris@1464 1687
Chris@1464 1688 assert issue.assignable_users.include?(non_project_member)
Chris@1464 1689 end
Chris@1464 1690
Chris@1464 1691 test "#assignable_users should include the current assignee" do
Chris@1464 1692 user = User.generate!
Chris@1464 1693 issue = Issue.generate!(:assigned_to => user)
Chris@1464 1694 user.lock!
Chris@1464 1695
Chris@1464 1696 assert Issue.find(issue.id).assignable_users.include?(user)
Chris@1464 1697 end
Chris@1464 1698
Chris@1464 1699 test "#assignable_users should not show the issue author twice" do
Chris@1464 1700 assignable_user_ids = Issue.find(1).assignable_users.collect(&:id)
Chris@1464 1701 assert_equal 2, assignable_user_ids.length
Chris@1464 1702
Chris@1464 1703 assignable_user_ids.each do |user_id|
Chris@1464 1704 assert_equal 1, assignable_user_ids.select {|i| i == user_id}.length,
Chris@1464 1705 "User #{user_id} appears more or less than once"
chris@22 1706 end
chris@22 1707 end
chris@37 1708
Chris@1464 1709 test "#assignable_users with issue_group_assignment should include groups" do
Chris@1464 1710 issue = Issue.new(:project => Project.find(2))
Chris@1464 1711
Chris@1464 1712 with_settings :issue_group_assignment => '1' do
Chris@1464 1713 assert_equal %w(Group User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
Chris@1464 1714 assert issue.assignable_users.include?(Group.find(11))
chris@37 1715 end
Chris@1464 1716 end
chris@37 1717
Chris@1464 1718 test "#assignable_users without issue_group_assignment should not include groups" do
Chris@1464 1719 issue = Issue.new(:project => Project.find(2))
chris@37 1720
Chris@1464 1721 with_settings :issue_group_assignment => '0' do
Chris@1464 1722 assert_equal %w(User), issue.assignable_users.map {|a| a.class.name}.uniq.sort
Chris@1464 1723 assert !issue.assignable_users.include?(Group.find(11))
Chris@909 1724 end
Chris@0 1725 end
Chris@441 1726
Chris@0 1727 def test_create_should_send_email_notification
Chris@0 1728 ActionMailer::Base.deliveries.clear
Chris@909 1729 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@909 1730 :author_id => 3, :status_id => 1,
Chris@909 1731 :priority => IssuePriority.all.first,
Chris@909 1732 :subject => 'test_create', :estimated_hours => '1:30')
Chris@1517 1733 with_settings :notified_events => %w(issue_added) do
Chris@1517 1734 assert issue.save
Chris@1517 1735 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@1517 1736 end
Chris@1517 1737 end
Chris@0 1738
Chris@1517 1739 def test_create_should_send_one_email_notification_with_both_settings
Chris@1517 1740 ActionMailer::Base.deliveries.clear
Chris@1517 1741 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1517 1742 :author_id => 3, :status_id => 1,
Chris@1517 1743 :priority => IssuePriority.all.first,
Chris@1517 1744 :subject => 'test_create', :estimated_hours => '1:30')
Chris@1517 1745 with_settings :notified_events => %w(issue_added issue_updated) do
Chris@1517 1746 assert issue.save
Chris@1517 1747 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@1517 1748 end
Chris@1517 1749 end
Chris@1517 1750
Chris@1517 1751 def test_create_should_not_send_email_notification_with_no_setting
Chris@1517 1752 ActionMailer::Base.deliveries.clear
Chris@1517 1753 issue = Issue.new(:project_id => 1, :tracker_id => 1,
Chris@1517 1754 :author_id => 3, :status_id => 1,
Chris@1517 1755 :priority => IssuePriority.all.first,
Chris@1517 1756 :subject => 'test_create', :estimated_hours => '1:30')
Chris@1517 1757 with_settings :notified_events => [] do
Chris@1517 1758 assert issue.save
Chris@1517 1759 assert_equal 0, ActionMailer::Base.deliveries.size
Chris@1517 1760 end
Chris@0 1761 end
chris@37 1762
Chris@1464 1763 def test_update_should_notify_previous_assignee
Chris@1464 1764 ActionMailer::Base.deliveries.clear
Chris@1464 1765 user = User.find(3)
Chris@1464 1766 user.members.update_all ["mail_notification = ?", false]
Chris@1464 1767 user.update_attribute :mail_notification, 'only_assigned'
Chris@1464 1768
Chris@1464 1769 issue = Issue.find(2)
Chris@1464 1770 issue.init_journal User.find(1)
Chris@1464 1771 issue.assigned_to = nil
Chris@1464 1772 issue.save!
Chris@1464 1773 assert_include user.mail, ActionMailer::Base.deliveries.last.bcc
Chris@1464 1774 end
Chris@1464 1775
Chris@0 1776 def test_stale_issue_should_not_send_email_notification
Chris@0 1777 ActionMailer::Base.deliveries.clear
Chris@0 1778 issue = Issue.find(1)
Chris@0 1779 stale = Issue.find(1)
Chris@441 1780
Chris@0 1781 issue.init_journal(User.find(1))
Chris@0 1782 issue.subject = 'Subjet update'
Chris@1517 1783 with_settings :notified_events => %w(issue_updated) do
Chris@1517 1784 assert issue.save
Chris@1517 1785 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@1517 1786 ActionMailer::Base.deliveries.clear
Chris@441 1787
Chris@1517 1788 stale.init_journal(User.find(1))
Chris@1517 1789 stale.subject = 'Another subjet update'
Chris@1517 1790 assert_raise ActiveRecord::StaleObjectError do
Chris@1517 1791 stale.save
Chris@1517 1792 end
Chris@1517 1793 assert ActionMailer::Base.deliveries.empty?
Chris@0 1794 end
Chris@0 1795 end
Chris@441 1796
Chris@245 1797 def test_journalized_description
Chris@245 1798 IssueCustomField.delete_all
Chris@441 1799
Chris@245 1800 i = Issue.first
Chris@245 1801 old_description = i.description
Chris@245 1802 new_description = "This is the new description"
Chris@441 1803
Chris@245 1804 i.init_journal(User.find(2))
Chris@245 1805 i.description = new_description
Chris@245 1806 assert_difference 'Journal.count', 1 do
Chris@245 1807 assert_difference 'JournalDetail.count', 1 do
Chris@245 1808 i.save!
Chris@245 1809 end
Chris@245 1810 end
Chris@441 1811
Chris@1517 1812 detail = JournalDetail.order('id DESC').first
Chris@245 1813 assert_equal i, detail.journal.journalized
Chris@245 1814 assert_equal 'attr', detail.property
Chris@245 1815 assert_equal 'description', detail.prop_key
Chris@245 1816 assert_equal old_description, detail.old_value
Chris@245 1817 assert_equal new_description, detail.value
Chris@245 1818 end
Chris@909 1819
Chris@507 1820 def test_blank_descriptions_should_not_be_journalized
Chris@507 1821 IssueCustomField.delete_all
Chris@1517 1822 Issue.where(:id => 1).update_all("description = NULL")
Chris@909 1823
Chris@507 1824 i = Issue.find(1)
Chris@507 1825 i.init_journal(User.find(2))
Chris@507 1826 i.subject = "blank description"
Chris@507 1827 i.description = "\r\n"
Chris@909 1828
Chris@507 1829 assert_difference 'Journal.count', 1 do
Chris@507 1830 assert_difference 'JournalDetail.count', 1 do
Chris@507 1831 i.save!
Chris@507 1832 end
Chris@507 1833 end
Chris@507 1834 end
Chris@909 1835
Chris@1115 1836 def test_journalized_multi_custom_field
Chris@1115 1837 field = IssueCustomField.create!(:name => 'filter', :field_format => 'list',
Chris@1115 1838 :is_filter => true, :is_for_all => true,
Chris@1115 1839 :tracker_ids => [1],
Chris@1115 1840 :possible_values => ['value1', 'value2', 'value3'],
Chris@1115 1841 :multiple => true)
Chris@1115 1842
Chris@1115 1843 issue = Issue.create!(:project_id => 1, :tracker_id => 1,
Chris@1115 1844 :subject => 'Test', :author_id => 1)
Chris@1115 1845
Chris@1115 1846 assert_difference 'Journal.count' do
Chris@1115 1847 assert_difference 'JournalDetail.count' do
Chris@1115 1848 issue.init_journal(User.first)
Chris@1115 1849 issue.custom_field_values = {field.id => ['value1']}
Chris@1115 1850 issue.save!
Chris@1115 1851 end
Chris@1115 1852 assert_difference 'JournalDetail.count' do
Chris@1115 1853 issue.init_journal(User.first)
Chris@1115 1854 issue.custom_field_values = {field.id => ['value1', 'value2']}
Chris@1115 1855 issue.save!
Chris@1115 1856 end
Chris@1115 1857 assert_difference 'JournalDetail.count', 2 do
Chris@1115 1858 issue.init_journal(User.first)
Chris@1115 1859 issue.custom_field_values = {field.id => ['value3', 'value2']}
Chris@1115 1860 issue.save!
Chris@1115 1861 end
Chris@1115 1862 assert_difference 'JournalDetail.count', 2 do
Chris@1115 1863 issue.init_journal(User.first)
Chris@1115 1864 issue.custom_field_values = {field.id => nil}
Chris@1115 1865 issue.save!
Chris@1115 1866 end
Chris@1115 1867 end
Chris@1115 1868 end
Chris@1115 1869
Chris@507 1870 def test_description_eol_should_be_normalized
Chris@507 1871 i = Issue.new(:description => "CR \r LF \n CRLF \r\n")
Chris@507 1872 assert_equal "CR \r\n LF \r\n CRLF \r\n", i.description
Chris@507 1873 end
Chris@441 1874
Chris@0 1875 def test_saving_twice_should_not_duplicate_journal_details
Chris@1464 1876 i = Issue.first
Chris@0 1877 i.init_journal(User.find(2), 'Some notes')
Chris@0 1878 # initial changes
Chris@0 1879 i.subject = 'New subject'
Chris@0 1880 i.done_ratio = i.done_ratio + 10
Chris@0 1881 assert_difference 'Journal.count' do
Chris@0 1882 assert i.save
Chris@0 1883 end
Chris@0 1884 # 1 more change
Chris@1464 1885 i.priority = IssuePriority.where("id <> ?", i.priority_id).first
Chris@0 1886 assert_no_difference 'Journal.count' do
Chris@0 1887 assert_difference 'JournalDetail.count', 1 do
Chris@0 1888 i.save
Chris@0 1889 end
Chris@0 1890 end
Chris@0 1891 # no more change
Chris@0 1892 assert_no_difference 'Journal.count' do
Chris@0 1893 assert_no_difference 'JournalDetail.count' do
Chris@0 1894 i.save
Chris@0 1895 end
Chris@0 1896 end
Chris@0 1897 end
Chris@0 1898
Chris@128 1899 def test_all_dependent_issues
Chris@128 1900 IssueRelation.delete_all
Chris@909 1901 assert IssueRelation.create!(:issue_from => Issue.find(1),
Chris@909 1902 :issue_to => Issue.find(2),
Chris@909 1903 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 1904 assert IssueRelation.create!(:issue_from => Issue.find(2),
Chris@909 1905 :issue_to => Issue.find(3),
Chris@909 1906 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 1907 assert IssueRelation.create!(:issue_from => Issue.find(3),
Chris@909 1908 :issue_to => Issue.find(8),
Chris@909 1909 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@441 1910
Chris@128 1911 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
Chris@128 1912 end
Chris@128 1913
Chris@1464 1914 def test_all_dependent_issues_with_subtask
Chris@1464 1915 IssueRelation.delete_all
Chris@1464 1916
Chris@1464 1917 project = Project.generate!(:name => "testproject")
Chris@1464 1918
Chris@1464 1919 parentIssue = Issue.generate!(:project => project)
Chris@1464 1920 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
Chris@1464 1921 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
Chris@1464 1922
Chris@1464 1923 assert_equal [childIssue1.id, childIssue2.id].sort, parentIssue.all_dependent_issues.collect(&:id).uniq.sort
Chris@1464 1924 end
Chris@1464 1925
Chris@1464 1926 def test_all_dependent_issues_does_not_include_self
Chris@1464 1927 IssueRelation.delete_all
Chris@1464 1928
Chris@1464 1929 project = Project.generate!(:name => "testproject")
Chris@1464 1930
Chris@1464 1931 parentIssue = Issue.generate!(:project => project)
Chris@1464 1932 childIssue = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
Chris@1464 1933
Chris@1464 1934 assert_equal [childIssue.id], parentIssue.all_dependent_issues.collect(&:id)
Chris@1464 1935 end
Chris@1464 1936
Chris@1464 1937 def test_all_dependent_issues_with_parenttask_and_sibling
Chris@1464 1938 IssueRelation.delete_all
Chris@1464 1939
Chris@1464 1940 project = Project.generate!(:name => "testproject")
Chris@1464 1941
Chris@1464 1942 parentIssue = Issue.generate!(:project => project)
Chris@1464 1943 childIssue1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
Chris@1464 1944 childIssue2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue.id)
Chris@1464 1945
Chris@1464 1946 assert_equal [parentIssue.id].sort, childIssue1.all_dependent_issues.collect(&:id)
Chris@1464 1947 end
Chris@1464 1948
Chris@1464 1949 def test_all_dependent_issues_with_relation_to_leaf_in_other_tree
Chris@1464 1950 IssueRelation.delete_all
Chris@1464 1951
Chris@1464 1952 project = Project.generate!(:name => "testproject")
Chris@1464 1953
Chris@1464 1954 parentIssue1 = Issue.generate!(:project => project)
Chris@1464 1955 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
Chris@1464 1956 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
Chris@1464 1957
Chris@1464 1958 parentIssue2 = Issue.generate!(:project => project)
Chris@1464 1959 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
Chris@1464 1960 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
Chris@1464 1961
Chris@1464 1962
Chris@1464 1963 assert IssueRelation.create(:issue_from => parentIssue1,
Chris@1464 1964 :issue_to => childIssue2_2,
Chris@1464 1965 :relation_type => IssueRelation::TYPE_BLOCKS)
Chris@1464 1966
Chris@1464 1967 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_2.id].sort,
Chris@1464 1968 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
Chris@1464 1969 end
Chris@1464 1970
Chris@1464 1971 def test_all_dependent_issues_with_relation_to_parent_in_other_tree
Chris@1464 1972 IssueRelation.delete_all
Chris@1464 1973
Chris@1464 1974 project = Project.generate!(:name => "testproject")
Chris@1464 1975
Chris@1464 1976 parentIssue1 = Issue.generate!(:project => project)
Chris@1464 1977 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
Chris@1464 1978 childIssue1_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
Chris@1464 1979
Chris@1464 1980 parentIssue2 = Issue.generate!(:project => project)
Chris@1464 1981 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
Chris@1464 1982 childIssue2_2 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
Chris@1464 1983
Chris@1464 1984
Chris@1464 1985 assert IssueRelation.create(:issue_from => parentIssue1,
Chris@1464 1986 :issue_to => parentIssue2,
Chris@1464 1987 :relation_type => IssueRelation::TYPE_BLOCKS)
Chris@1464 1988
Chris@1464 1989 assert_equal [childIssue1_1.id, childIssue1_2.id, parentIssue2.id, childIssue2_1.id, childIssue2_2.id].sort,
Chris@1464 1990 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
Chris@1464 1991 end
Chris@1464 1992
Chris@1464 1993 def test_all_dependent_issues_with_transitive_relation
Chris@1464 1994 IssueRelation.delete_all
Chris@1464 1995
Chris@1464 1996 project = Project.generate!(:name => "testproject")
Chris@1464 1997
Chris@1464 1998 parentIssue1 = Issue.generate!(:project => project)
Chris@1464 1999 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
Chris@1464 2000
Chris@1464 2001 parentIssue2 = Issue.generate!(:project => project)
Chris@1464 2002 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
Chris@1464 2003
Chris@1464 2004 independentIssue = Issue.generate!(:project => project)
Chris@1464 2005
Chris@1464 2006 assert IssueRelation.create(:issue_from => parentIssue1,
Chris@1464 2007 :issue_to => childIssue2_1,
Chris@1464 2008 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1464 2009
Chris@1464 2010 assert IssueRelation.create(:issue_from => childIssue2_1,
Chris@1464 2011 :issue_to => independentIssue,
Chris@1464 2012 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1464 2013
Chris@1464 2014 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
Chris@1464 2015 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
Chris@1464 2016 end
Chris@1464 2017
Chris@1464 2018 def test_all_dependent_issues_with_transitive_relation2
Chris@1464 2019 IssueRelation.delete_all
Chris@1464 2020
Chris@1464 2021 project = Project.generate!(:name => "testproject")
Chris@1464 2022
Chris@1464 2023 parentIssue1 = Issue.generate!(:project => project)
Chris@1464 2024 childIssue1_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue1.id)
Chris@1464 2025
Chris@1464 2026 parentIssue2 = Issue.generate!(:project => project)
Chris@1464 2027 childIssue2_1 = Issue.generate!(:project => project, :parent_issue_id => parentIssue2.id)
Chris@1464 2028
Chris@1464 2029 independentIssue = Issue.generate!(:project => project)
Chris@1464 2030
Chris@1464 2031 assert IssueRelation.create(:issue_from => parentIssue1,
Chris@1464 2032 :issue_to => independentIssue,
Chris@1464 2033 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1464 2034
Chris@1464 2035 assert IssueRelation.create(:issue_from => independentIssue,
Chris@1464 2036 :issue_to => childIssue2_1,
Chris@1464 2037 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1464 2038
Chris@1464 2039 assert_equal [childIssue1_1.id, parentIssue2.id, childIssue2_1.id, independentIssue.id].sort,
Chris@1464 2040 parentIssue1.all_dependent_issues.collect(&:id).uniq.sort
Chris@1464 2041
Chris@1464 2042 end
Chris@1464 2043
Chris@128 2044 def test_all_dependent_issues_with_persistent_circular_dependency
Chris@128 2045 IssueRelation.delete_all
Chris@909 2046 assert IssueRelation.create!(:issue_from => Issue.find(1),
Chris@909 2047 :issue_to => Issue.find(2),
Chris@909 2048 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@909 2049 assert IssueRelation.create!(:issue_from => Issue.find(2),
Chris@909 2050 :issue_to => Issue.find(3),
Chris@909 2051 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@441 2052
Chris@1115 2053 r = IssueRelation.create!(:issue_from => Issue.find(3),
Chris@1115 2054 :issue_to => Issue.find(7),
Chris@1115 2055 :relation_type => IssueRelation::TYPE_PRECEDES)
Chris@1517 2056 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
Chris@1464 2057
Chris@128 2058 assert_equal [2, 3], Issue.find(1).all_dependent_issues.collect(&:id).sort
Chris@128 2059 end
Chris@441 2060
Chris@441 2061 def test_all_dependent_issues_with_persistent_multiple_circular_dependencies
Chris@441 2062 IssueRelation.delete_all
Chris@909 2063 assert IssueRelation.create!(:issue_from => Issue.find(1),
Chris@909 2064 :issue_to => Issue.find(2),
Chris@909 2065 :relation_type => IssueRelation::TYPE_RELATES)
Chris@909 2066 assert IssueRelation.create!(:issue_from => Issue.find(2),
Chris@909 2067 :issue_to => Issue.find(3),
Chris@909 2068 :relation_type => IssueRelation::TYPE_RELATES)
Chris@909 2069 assert IssueRelation.create!(:issue_from => Issue.find(3),
Chris@909 2070 :issue_to => Issue.find(8),
Chris@909 2071 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1115 2072
Chris@1115 2073 r = IssueRelation.create!(:issue_from => Issue.find(8),
Chris@1115 2074 :issue_to => Issue.find(7),
Chris@1115 2075 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1517 2076 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 2")
Chris@1464 2077
Chris@1115 2078 r = IssueRelation.create!(:issue_from => Issue.find(3),
Chris@1115 2079 :issue_to => Issue.find(7),
Chris@1115 2080 :relation_type => IssueRelation::TYPE_RELATES)
Chris@1517 2081 IssueRelation.where(["id = ?", r.id]).update_all("issue_to_id = 1")
Chris@441 2082
Chris@441 2083 assert_equal [2, 3, 8], Issue.find(1).all_dependent_issues.collect(&:id).sort
Chris@441 2084 end
Chris@441 2085
Chris@1464 2086 test "#done_ratio should use the issue_status according to Setting.issue_done_ratio" do
Chris@1464 2087 @issue = Issue.find(1)
Chris@1464 2088 @issue_status = IssueStatus.find(1)
Chris@1464 2089 @issue_status.update_attribute(:default_done_ratio, 50)
Chris@1464 2090 @issue2 = Issue.find(2)
Chris@1464 2091 @issue_status2 = IssueStatus.find(2)
Chris@1464 2092 @issue_status2.update_attribute(:default_done_ratio, 0)
Chris@1464 2093
Chris@1464 2094 with_settings :issue_done_ratio => 'issue_field' do
Chris@1464 2095 assert_equal 0, @issue.done_ratio
Chris@1464 2096 assert_equal 30, @issue2.done_ratio
Chris@0 2097 end
Chris@441 2098
Chris@1464 2099 with_settings :issue_done_ratio => 'issue_status' do
Chris@1464 2100 assert_equal 50, @issue.done_ratio
Chris@1464 2101 assert_equal 0, @issue2.done_ratio
Chris@0 2102 end
Chris@0 2103 end
Chris@0 2104
Chris@1464 2105 test "#update_done_ratio_from_issue_status should update done_ratio according to Setting.issue_done_ratio" do
Chris@1464 2106 @issue = Issue.find(1)
Chris@1464 2107 @issue_status = IssueStatus.find(1)
Chris@1464 2108 @issue_status.update_attribute(:default_done_ratio, 50)
Chris@1464 2109 @issue2 = Issue.find(2)
Chris@1464 2110 @issue_status2 = IssueStatus.find(2)
Chris@1464 2111 @issue_status2.update_attribute(:default_done_ratio, 0)
Chris@1464 2112
Chris@1464 2113 with_settings :issue_done_ratio => 'issue_field' do
Chris@1464 2114 @issue.update_done_ratio_from_issue_status
Chris@1464 2115 @issue2.update_done_ratio_from_issue_status
Chris@1464 2116
Chris@1464 2117 assert_equal 0, @issue.read_attribute(:done_ratio)
Chris@1464 2118 assert_equal 30, @issue2.read_attribute(:done_ratio)
Chris@0 2119 end
Chris@441 2120
Chris@1464 2121 with_settings :issue_done_ratio => 'issue_status' do
Chris@1464 2122 @issue.update_done_ratio_from_issue_status
Chris@1464 2123 @issue2.update_done_ratio_from_issue_status
Chris@441 2124
Chris@1464 2125 assert_equal 50, @issue.read_attribute(:done_ratio)
Chris@1464 2126 assert_equal 0, @issue2.read_attribute(:done_ratio)
Chris@0 2127 end
Chris@0 2128 end
Chris@0 2129
Chris@0 2130 test "#by_tracker" do
Chris@441 2131 User.current = User.anonymous
Chris@0 2132 groups = Issue.by_tracker(Project.find(1))
Chris@1464 2133 assert_equal 3, groups.count
Chris@0 2134 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2135 end
Chris@0 2136
Chris@0 2137 test "#by_version" do
Chris@441 2138 User.current = User.anonymous
Chris@0 2139 groups = Issue.by_version(Project.find(1))
Chris@1464 2140 assert_equal 3, groups.count
Chris@0 2141 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2142 end
Chris@0 2143
Chris@0 2144 test "#by_priority" do
Chris@441 2145 User.current = User.anonymous
Chris@0 2146 groups = Issue.by_priority(Project.find(1))
Chris@1464 2147 assert_equal 4, groups.count
Chris@0 2148 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2149 end
Chris@0 2150
Chris@0 2151 test "#by_category" do
Chris@441 2152 User.current = User.anonymous
Chris@0 2153 groups = Issue.by_category(Project.find(1))
Chris@1464 2154 assert_equal 2, groups.count
Chris@0 2155 assert_equal 3, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2156 end
Chris@0 2157
Chris@0 2158 test "#by_assigned_to" do
Chris@441 2159 User.current = User.anonymous
Chris@0 2160 groups = Issue.by_assigned_to(Project.find(1))
Chris@1464 2161 assert_equal 2, groups.count
Chris@0 2162 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2163 end
Chris@0 2164
Chris@0 2165 test "#by_author" do
Chris@441 2166 User.current = User.anonymous
Chris@0 2167 groups = Issue.by_author(Project.find(1))
Chris@1464 2168 assert_equal 4, groups.count
Chris@0 2169 assert_equal 7, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2170 end
Chris@0 2171
Chris@0 2172 test "#by_subproject" do
Chris@441 2173 User.current = User.anonymous
Chris@0 2174 groups = Issue.by_subproject(Project.find(1))
Chris@441 2175 # Private descendant not visible
Chris@1464 2176 assert_equal 1, groups.count
Chris@441 2177 assert_equal 2, groups.inject(0) {|sum, group| sum + group['total'].to_i}
Chris@0 2178 end
Chris@441 2179
Chris@1115 2180 def test_recently_updated_scope
Chris@0 2181 #should return the last updated issue
Chris@1115 2182 assert_equal Issue.reorder("updated_on DESC").first, Issue.recently_updated.limit(1).first
Chris@0 2183 end
Chris@0 2184
Chris@0 2185 def test_on_active_projects_scope
Chris@0 2186 assert Project.find(2).archive
Chris@441 2187
Chris@0 2188 before = Issue.on_active_project.length
Chris@0 2189 # test inclusion to results
Chris@1115 2190 issue = Issue.generate!(:tracker => Project.find(2).trackers.first)
Chris@0 2191 assert_equal before + 1, Issue.on_active_project.length
Chris@0 2192
Chris@0 2193 # Move to an archived project
Chris@0 2194 issue.project = Project.find(2)
Chris@0 2195 assert issue.save
Chris@0 2196 assert_equal before, Issue.on_active_project.length
Chris@0 2197 end
chris@37 2198
Chris@1464 2199 test "Issue#recipients should include project recipients" do
Chris@1464 2200 issue = Issue.generate!
Chris@1464 2201 assert issue.project.recipients.present?
Chris@1464 2202 issue.project.recipients.each do |project_recipient|
Chris@1464 2203 assert issue.recipients.include?(project_recipient)
chris@37 2204 end
Chris@1464 2205 end
Chris@441 2206
Chris@1464 2207 test "Issue#recipients should include the author if the author is active" do
Chris@1464 2208 issue = Issue.generate!(:author => User.generate!)
Chris@1464 2209 assert issue.author, "No author set for Issue"
Chris@1464 2210 assert issue.recipients.include?(issue.author.mail)
Chris@1464 2211 end
chris@37 2212
Chris@1464 2213 test "Issue#recipients should include the assigned to user if the assigned to user is active" do
Chris@1464 2214 issue = Issue.generate!(:assigned_to => User.generate!)
Chris@1464 2215 assert issue.assigned_to, "No assigned_to set for Issue"
Chris@1464 2216 assert issue.recipients.include?(issue.assigned_to.mail)
Chris@1464 2217 end
Chris@441 2218
Chris@1464 2219 test "Issue#recipients should not include users who opt out of all email" do
Chris@1464 2220 issue = Issue.generate!(:author => User.generate!)
Chris@1464 2221 issue.author.update_attribute(:mail_notification, :none)
Chris@1464 2222 assert !issue.recipients.include?(issue.author.mail)
Chris@1464 2223 end
chris@37 2224
Chris@1464 2225 test "Issue#recipients should not include the issue author if they are only notified of assigned issues" do
Chris@1464 2226 issue = Issue.generate!(:author => User.generate!)
Chris@1464 2227 issue.author.update_attribute(:mail_notification, :only_assigned)
Chris@1464 2228 assert !issue.recipients.include?(issue.author.mail)
Chris@1464 2229 end
chris@37 2230
Chris@1464 2231 test "Issue#recipients should not include the assigned user if they are only notified of owned issues" do
Chris@1464 2232 issue = Issue.generate!(:assigned_to => User.generate!)
Chris@1464 2233 issue.assigned_to.update_attribute(:mail_notification, :only_owner)
Chris@1464 2234 assert !issue.recipients.include?(issue.assigned_to.mail)
Chris@1115 2235 end
chris@37 2236
Chris@1115 2237 def test_last_journal_id_with_journals_should_return_the_journal_id
Chris@1115 2238 assert_equal 2, Issue.find(1).last_journal_id
Chris@1115 2239 end
Chris@1115 2240
Chris@1115 2241 def test_last_journal_id_without_journals_should_return_nil
Chris@1115 2242 assert_nil Issue.find(3).last_journal_id
Chris@1115 2243 end
Chris@1115 2244
Chris@1115 2245 def test_journals_after_should_return_journals_with_greater_id
Chris@1115 2246 assert_equal [Journal.find(2)], Issue.find(1).journals_after('1')
Chris@1115 2247 assert_equal [], Issue.find(1).journals_after('2')
Chris@1115 2248 end
Chris@1115 2249
Chris@1115 2250 def test_journals_after_with_blank_arg_should_return_all_journals
Chris@1115 2251 assert_equal [Journal.find(1), Journal.find(2)], Issue.find(1).journals_after('')
Chris@1115 2252 end
Chris@1115 2253
Chris@1464 2254 def test_css_classes_should_include_tracker
Chris@1464 2255 issue = Issue.new(:tracker => Tracker.find(2))
Chris@1464 2256 classes = issue.css_classes.split(' ')
Chris@1464 2257 assert_include 'tracker-2', classes
Chris@1464 2258 end
Chris@1464 2259
Chris@1115 2260 def test_css_classes_should_include_priority
Chris@1115 2261 issue = Issue.new(:priority => IssuePriority.find(8))
Chris@1115 2262 classes = issue.css_classes.split(' ')
Chris@1115 2263 assert_include 'priority-8', classes
Chris@1115 2264 assert_include 'priority-highest', classes
Chris@1115 2265 end
Chris@1115 2266
Chris@1494 2267 def test_css_classes_should_include_user_and_group_assignment
Chris@1494 2268 project = Project.first
Chris@1494 2269 user = User.generate!
Chris@1494 2270 group = Group.generate!
Chris@1494 2271 Member.create!(:principal => group, :project => project, :role_ids => [1, 2])
Chris@1494 2272 group.users << user
Chris@1494 2273 assert user.member_of?(project)
Chris@1494 2274 issue1 = Issue.generate(:assigned_to_id => group.id)
Chris@1494 2275 assert_include 'assigned-to-my-group', issue1.css_classes(user)
Chris@1494 2276 assert_not_include 'assigned-to-me', issue1.css_classes(user)
Chris@1494 2277 issue2 = Issue.generate(:assigned_to_id => user.id)
Chris@1494 2278 assert_not_include 'assigned-to-my-group', issue2.css_classes(user)
Chris@1494 2279 assert_include 'assigned-to-me', issue2.css_classes(user)
Chris@1464 2280 end
Chris@1464 2281
Chris@1115 2282 def test_save_attachments_with_hash_should_save_attachments_in_keys_order
Chris@1115 2283 set_tmp_attachments_directory
Chris@1115 2284 issue = Issue.generate!
Chris@1115 2285 issue.save_attachments({
Chris@1115 2286 'p0' => {'file' => mock_file_with_options(:original_filename => 'upload')},
Chris@1115 2287 '3' => {'file' => mock_file_with_options(:original_filename => 'bar')},
Chris@1115 2288 '1' => {'file' => mock_file_with_options(:original_filename => 'foo')}
Chris@1115 2289 })
Chris@1115 2290 issue.attach_saved_attachments
Chris@1115 2291
Chris@1115 2292 assert_equal 3, issue.reload.attachments.count
Chris@1115 2293 assert_equal %w(upload foo bar), issue.attachments.map(&:filename)
chris@37 2294 end
Chris@1464 2295
Chris@1464 2296 def test_closed_on_should_be_nil_when_creating_an_open_issue
Chris@1464 2297 issue = Issue.generate!(:status_id => 1).reload
Chris@1464 2298 assert !issue.closed?
Chris@1464 2299 assert_nil issue.closed_on
Chris@1464 2300 end
Chris@1464 2301
Chris@1464 2302 def test_closed_on_should_be_set_when_creating_a_closed_issue
Chris@1464 2303 issue = Issue.generate!(:status_id => 5).reload
Chris@1464 2304 assert issue.closed?
Chris@1464 2305 assert_not_nil issue.closed_on
Chris@1464 2306 assert_equal issue.updated_on, issue.closed_on
Chris@1464 2307 assert_equal issue.created_on, issue.closed_on
Chris@1464 2308 end
Chris@1464 2309
Chris@1464 2310 def test_closed_on_should_be_nil_when_updating_an_open_issue
Chris@1464 2311 issue = Issue.find(1)
Chris@1464 2312 issue.subject = 'Not closed yet'
Chris@1464 2313 issue.save!
Chris@1464 2314 issue.reload
Chris@1464 2315 assert_nil issue.closed_on
Chris@1464 2316 end
Chris@1464 2317
Chris@1464 2318 def test_closed_on_should_be_set_when_closing_an_open_issue
Chris@1464 2319 issue = Issue.find(1)
Chris@1464 2320 issue.subject = 'Now closed'
Chris@1464 2321 issue.status_id = 5
Chris@1464 2322 issue.save!
Chris@1464 2323 issue.reload
Chris@1464 2324 assert_not_nil issue.closed_on
Chris@1464 2325 assert_equal issue.updated_on, issue.closed_on
Chris@1464 2326 end
Chris@1464 2327
Chris@1464 2328 def test_closed_on_should_not_be_updated_when_updating_a_closed_issue
Chris@1464 2329 issue = Issue.open(false).first
Chris@1464 2330 was_closed_on = issue.closed_on
Chris@1464 2331 assert_not_nil was_closed_on
Chris@1464 2332 issue.subject = 'Updating a closed issue'
Chris@1464 2333 issue.save!
Chris@1464 2334 issue.reload
Chris@1464 2335 assert_equal was_closed_on, issue.closed_on
Chris@1464 2336 end
Chris@1464 2337
Chris@1464 2338 def test_closed_on_should_be_preserved_when_reopening_a_closed_issue
Chris@1464 2339 issue = Issue.open(false).first
Chris@1464 2340 was_closed_on = issue.closed_on
Chris@1464 2341 assert_not_nil was_closed_on
Chris@1464 2342 issue.subject = 'Reopening a closed issue'
Chris@1464 2343 issue.status_id = 1
Chris@1464 2344 issue.save!
Chris@1464 2345 issue.reload
Chris@1464 2346 assert !issue.closed?
Chris@1464 2347 assert_equal was_closed_on, issue.closed_on
Chris@1464 2348 end
Chris@1464 2349
Chris@1464 2350 def test_status_was_should_return_nil_for_new_issue
Chris@1464 2351 issue = Issue.new
Chris@1464 2352 assert_nil issue.status_was
Chris@1464 2353 end
Chris@1464 2354
Chris@1464 2355 def test_status_was_should_return_status_before_change
Chris@1464 2356 issue = Issue.find(1)
Chris@1464 2357 issue.status = IssueStatus.find(2)
Chris@1464 2358 assert_equal IssueStatus.find(1), issue.status_was
Chris@1464 2359 end
Chris@1464 2360
Chris@1464 2361 def test_status_was_should_be_reset_on_save
Chris@1464 2362 issue = Issue.find(1)
Chris@1464 2363 issue.status = IssueStatus.find(2)
Chris@1464 2364 assert_equal IssueStatus.find(1), issue.status_was
Chris@1464 2365 assert issue.save!
Chris@1464 2366 assert_equal IssueStatus.find(2), issue.status_was
Chris@1464 2367 end
Chris@0 2368 end