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