annotate .svn/pristine/90/901615ad1db66e2bf6c218140437d9f8b1aaad5a.svn-base @ 1524:82fac3dcf466 redmine-2.5-integration

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