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