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