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