##// END OF EJS Templates
Fixed potential test failure....
Jean-Philippe Lang -
r8904:774e5f3b5edf
parent child
Show More
@@ -1,1179 +1,1179
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 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 ProjectTest < ActiveSupport::TestCase
21 21 fixtures :projects, :trackers, :issue_statuses, :issues,
22 22 :journals, :journal_details,
23 23 :enumerations, :users, :issue_categories,
24 24 :projects_trackers,
25 25 :custom_fields,
26 26 :custom_fields_projects,
27 27 :custom_fields_trackers,
28 28 :custom_values,
29 29 :roles,
30 30 :member_roles,
31 31 :members,
32 32 :enabled_modules,
33 33 :workflows,
34 34 :versions,
35 35 :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
36 36 :groups_users,
37 37 :boards,
38 38 :repositories
39 39
40 40 def setup
41 41 @ecookbook = Project.find(1)
42 42 @ecookbook_sub1 = Project.find(3)
43 43 set_tmp_attachments_directory
44 44 User.current = nil
45 45 end
46 46
47 47 should_validate_presence_of :name
48 48 should_validate_presence_of :identifier
49 49
50 50 should_validate_uniqueness_of :identifier
51 51
52 52 context "associations" do
53 53 should_have_many :members
54 54 should_have_many :users, :through => :members
55 55 should_have_many :member_principals
56 56 should_have_many :principals, :through => :member_principals
57 57 should_have_many :enabled_modules
58 58 should_have_many :issues
59 59 should_have_many :issue_changes, :through => :issues
60 60 should_have_many :versions
61 61 should_have_many :time_entries
62 62 should_have_many :queries
63 63 should_have_many :documents
64 64 should_have_many :news
65 65 should_have_many :issue_categories
66 66 should_have_many :boards
67 67 should_have_many :changesets, :through => :repository
68 68
69 69 should_have_one :repository
70 70 should_have_one :wiki
71 71
72 72 should_have_and_belong_to_many :trackers
73 73 should_have_and_belong_to_many :issue_custom_fields
74 74 end
75 75
76 76 def test_truth
77 77 assert_kind_of Project, @ecookbook
78 78 assert_equal "eCookbook", @ecookbook.name
79 79 end
80 80
81 81 def test_default_attributes
82 82 with_settings :default_projects_public => '1' do
83 83 assert_equal true, Project.new.is_public
84 84 assert_equal false, Project.new(:is_public => false).is_public
85 85 end
86 86
87 87 with_settings :default_projects_public => '0' do
88 88 assert_equal false, Project.new.is_public
89 89 assert_equal true, Project.new(:is_public => true).is_public
90 90 end
91 91
92 92 with_settings :sequential_project_identifiers => '1' do
93 93 assert !Project.new.identifier.blank?
94 94 assert Project.new(:identifier => '').identifier.blank?
95 95 end
96 96
97 97 with_settings :sequential_project_identifiers => '0' do
98 98 assert Project.new.identifier.blank?
99 99 assert !Project.new(:identifier => 'test').blank?
100 100 end
101 101
102 102 with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
103 103 assert_equal ['issue_tracking', 'repository'], Project.new.enabled_module_names
104 104 end
105 105
106 106 assert_equal Tracker.all, Project.new.trackers
107 assert_equal Tracker.find(1, 3), Project.new(:tracker_ids => [1, 3]).trackers
107 assert_equal Tracker.find(1, 3).sort, Project.new(:tracker_ids => [1, 3]).trackers.sort
108 108 end
109 109
110 110 def test_update
111 111 assert_equal "eCookbook", @ecookbook.name
112 112 @ecookbook.name = "eCook"
113 113 assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ")
114 114 @ecookbook.reload
115 115 assert_equal "eCook", @ecookbook.name
116 116 end
117 117
118 118 def test_validate_identifier
119 119 to_test = {"abc" => true,
120 120 "ab12" => true,
121 121 "ab-12" => true,
122 122 "ab_12" => true,
123 123 "12" => false,
124 124 "new" => false}
125 125
126 126 to_test.each do |identifier, valid|
127 127 p = Project.new
128 128 p.identifier = identifier
129 129 p.valid?
130 130 if valid
131 131 assert p.errors['identifier'].blank?, "identifier #{identifier} was not valid"
132 132 else
133 133 assert p.errors['identifier'].present?, "identifier #{identifier} was valid"
134 134 end
135 135 end
136 136 end
137 137
138 138 def test_members_should_be_active_users
139 139 Project.all.each do |project|
140 140 assert_nil project.members.detect {|m| !(m.user.is_a?(User) && m.user.active?) }
141 141 end
142 142 end
143 143
144 144 def test_users_should_be_active_users
145 145 Project.all.each do |project|
146 146 assert_nil project.users.detect {|u| !(u.is_a?(User) && u.active?) }
147 147 end
148 148 end
149 149
150 150 def test_archive
151 151 user = @ecookbook.members.first.user
152 152 @ecookbook.archive
153 153 @ecookbook.reload
154 154
155 155 assert !@ecookbook.active?
156 156 assert @ecookbook.archived?
157 157 assert !user.projects.include?(@ecookbook)
158 158 # Subproject are also archived
159 159 assert !@ecookbook.children.empty?
160 160 assert @ecookbook.descendants.active.empty?
161 161 end
162 162
163 163 def test_archive_should_fail_if_versions_are_used_by_non_descendant_projects
164 164 # Assign an issue of a project to a version of a child project
165 165 Issue.find(4).update_attribute :fixed_version_id, 4
166 166
167 167 assert_no_difference "Project.count(:all, :conditions => 'status = #{Project::STATUS_ARCHIVED}')" do
168 168 assert_equal false, @ecookbook.archive
169 169 end
170 170 @ecookbook.reload
171 171 assert @ecookbook.active?
172 172 end
173 173
174 174 def test_unarchive
175 175 user = @ecookbook.members.first.user
176 176 @ecookbook.archive
177 177 # A subproject of an archived project can not be unarchived
178 178 assert !@ecookbook_sub1.unarchive
179 179
180 180 # Unarchive project
181 181 assert @ecookbook.unarchive
182 182 @ecookbook.reload
183 183 assert @ecookbook.active?
184 184 assert !@ecookbook.archived?
185 185 assert user.projects.include?(@ecookbook)
186 186 # Subproject can now be unarchived
187 187 @ecookbook_sub1.reload
188 188 assert @ecookbook_sub1.unarchive
189 189 end
190 190
191 191 def test_destroy
192 192 # 2 active members
193 193 assert_equal 2, @ecookbook.members.size
194 194 # and 1 is locked
195 195 assert_equal 3, Member.find(:all, :conditions => ['project_id = ?', @ecookbook.id]).size
196 196 # some boards
197 197 assert @ecookbook.boards.any?
198 198
199 199 @ecookbook.destroy
200 200 # make sure that the project non longer exists
201 201 assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
202 202 # make sure related data was removed
203 203 assert_nil Member.first(:conditions => {:project_id => @ecookbook.id})
204 204 assert_nil Board.first(:conditions => {:project_id => @ecookbook.id})
205 205 assert_nil Issue.first(:conditions => {:project_id => @ecookbook.id})
206 206 end
207 207
208 208 def test_destroying_root_projects_should_clear_data
209 209 Project.roots.each do |root|
210 210 root.destroy
211 211 end
212 212
213 213 assert_equal 0, Project.count, "Projects were not deleted: #{Project.all.inspect}"
214 214 assert_equal 0, Member.count, "Members were not deleted: #{Member.all.inspect}"
215 215 assert_equal 0, MemberRole.count
216 216 assert_equal 0, Issue.count
217 217 assert_equal 0, Journal.count
218 218 assert_equal 0, JournalDetail.count
219 219 assert_equal 0, Attachment.count
220 220 assert_equal 0, EnabledModule.count
221 221 assert_equal 0, IssueCategory.count
222 222 assert_equal 0, IssueRelation.count
223 223 assert_equal 0, Board.count
224 224 assert_equal 0, Message.count
225 225 assert_equal 0, News.count
226 226 assert_equal 0, Query.count(:conditions => "project_id IS NOT NULL")
227 227 assert_equal 0, Repository.count
228 228 assert_equal 0, Changeset.count
229 229 assert_equal 0, Change.count
230 230 assert_equal 0, Comment.count
231 231 assert_equal 0, TimeEntry.count
232 232 assert_equal 0, Version.count
233 233 assert_equal 0, Watcher.count
234 234 assert_equal 0, Wiki.count
235 235 assert_equal 0, WikiPage.count
236 236 assert_equal 0, WikiContent.count
237 237 assert_equal 0, WikiContent::Version.count
238 238 assert_equal 0, Project.connection.select_all("SELECT * FROM projects_trackers").size
239 239 assert_equal 0, Project.connection.select_all("SELECT * FROM custom_fields_projects").size
240 240 assert_equal 0, CustomValue.count(:conditions => {:customized_type => ['Project', 'Issue', 'TimeEntry', 'Version']})
241 241 end
242 242
243 243 def test_move_an_orphan_project_to_a_root_project
244 244 sub = Project.find(2)
245 245 sub.set_parent! @ecookbook
246 246 assert_equal @ecookbook.id, sub.parent.id
247 247 @ecookbook.reload
248 248 assert_equal 4, @ecookbook.children.size
249 249 end
250 250
251 251 def test_move_an_orphan_project_to_a_subproject
252 252 sub = Project.find(2)
253 253 assert sub.set_parent!(@ecookbook_sub1)
254 254 end
255 255
256 256 def test_move_a_root_project_to_a_project
257 257 sub = @ecookbook
258 258 assert sub.set_parent!(Project.find(2))
259 259 end
260 260
261 261 def test_should_not_move_a_project_to_its_children
262 262 sub = @ecookbook
263 263 assert !(sub.set_parent!(Project.find(3)))
264 264 end
265 265
266 266 def test_set_parent_should_add_roots_in_alphabetical_order
267 267 ProjectCustomField.delete_all
268 268 Project.delete_all
269 269 Project.create!(:name => 'Project C', :identifier => 'project-c').set_parent!(nil)
270 270 Project.create!(:name => 'Project B', :identifier => 'project-b').set_parent!(nil)
271 271 Project.create!(:name => 'Project D', :identifier => 'project-d').set_parent!(nil)
272 272 Project.create!(:name => 'Project A', :identifier => 'project-a').set_parent!(nil)
273 273
274 274 assert_equal 4, Project.count
275 275 assert_equal Project.all.sort_by(&:name), Project.all.sort_by(&:lft)
276 276 end
277 277
278 278 def test_set_parent_should_add_children_in_alphabetical_order
279 279 ProjectCustomField.delete_all
280 280 parent = Project.create!(:name => 'Parent', :identifier => 'parent')
281 281 Project.create!(:name => 'Project C', :identifier => 'project-c').set_parent!(parent)
282 282 Project.create!(:name => 'Project B', :identifier => 'project-b').set_parent!(parent)
283 283 Project.create!(:name => 'Project D', :identifier => 'project-d').set_parent!(parent)
284 284 Project.create!(:name => 'Project A', :identifier => 'project-a').set_parent!(parent)
285 285
286 286 parent.reload
287 287 assert_equal 4, parent.children.size
288 288 assert_equal parent.children.all.sort_by(&:name), parent.children.all
289 289 end
290 290
291 291 def test_rebuild_should_sort_children_alphabetically
292 292 ProjectCustomField.delete_all
293 293 parent = Project.create!(:name => 'Parent', :identifier => 'parent')
294 294 Project.create!(:name => 'Project C', :identifier => 'project-c').move_to_child_of(parent)
295 295 Project.create!(:name => 'Project B', :identifier => 'project-b').move_to_child_of(parent)
296 296 Project.create!(:name => 'Project D', :identifier => 'project-d').move_to_child_of(parent)
297 297 Project.create!(:name => 'Project A', :identifier => 'project-a').move_to_child_of(parent)
298 298
299 299 Project.update_all("lft = NULL, rgt = NULL")
300 300 Project.rebuild!
301 301
302 302 parent.reload
303 303 assert_equal 4, parent.children.size
304 304 assert_equal parent.children.all.sort_by(&:name), parent.children.all
305 305 end
306 306
307 307
308 308 def test_set_parent_should_update_issue_fixed_version_associations_when_a_fixed_version_is_moved_out_of_the_hierarchy
309 309 # Parent issue with a hierarchy project's fixed version
310 310 parent_issue = Issue.find(1)
311 311 parent_issue.update_attribute(:fixed_version_id, 4)
312 312 parent_issue.reload
313 313 assert_equal 4, parent_issue.fixed_version_id
314 314
315 315 # Should keep fixed versions for the issues
316 316 issue_with_local_fixed_version = Issue.find(5)
317 317 issue_with_local_fixed_version.update_attribute(:fixed_version_id, 4)
318 318 issue_with_local_fixed_version.reload
319 319 assert_equal 4, issue_with_local_fixed_version.fixed_version_id
320 320
321 321 # Local issue with hierarchy fixed_version
322 322 issue_with_hierarchy_fixed_version = Issue.find(13)
323 323 issue_with_hierarchy_fixed_version.update_attribute(:fixed_version_id, 6)
324 324 issue_with_hierarchy_fixed_version.reload
325 325 assert_equal 6, issue_with_hierarchy_fixed_version.fixed_version_id
326 326
327 327 # Move project out of the issue's hierarchy
328 328 moved_project = Project.find(3)
329 329 moved_project.set_parent!(Project.find(2))
330 330 parent_issue.reload
331 331 issue_with_local_fixed_version.reload
332 332 issue_with_hierarchy_fixed_version.reload
333 333
334 334 assert_equal 4, issue_with_local_fixed_version.fixed_version_id, "Fixed version was not keep on an issue local to the moved project"
335 335 assert_equal nil, issue_with_hierarchy_fixed_version.fixed_version_id, "Fixed version is still set after moving the Project out of the hierarchy where the version is defined in"
336 336 assert_equal nil, parent_issue.fixed_version_id, "Fixed version is still set after moving the Version out of the hierarchy for the issue."
337 337 end
338 338
339 339 def test_parent
340 340 p = Project.find(6).parent
341 341 assert p.is_a?(Project)
342 342 assert_equal 5, p.id
343 343 end
344 344
345 345 def test_ancestors
346 346 a = Project.find(6).ancestors
347 347 assert a.first.is_a?(Project)
348 348 assert_equal [1, 5], a.collect(&:id)
349 349 end
350 350
351 351 def test_root
352 352 r = Project.find(6).root
353 353 assert r.is_a?(Project)
354 354 assert_equal 1, r.id
355 355 end
356 356
357 357 def test_children
358 358 c = Project.find(1).children
359 359 assert c.first.is_a?(Project)
360 360 assert_equal [5, 3, 4], c.collect(&:id)
361 361 end
362 362
363 363 def test_descendants
364 364 d = Project.find(1).descendants
365 365 assert d.first.is_a?(Project)
366 366 assert_equal [5, 6, 3, 4], d.collect(&:id)
367 367 end
368 368
369 369 def test_allowed_parents_should_be_empty_for_non_member_user
370 370 Role.non_member.add_permission!(:add_project)
371 371 user = User.find(9)
372 372 assert user.memberships.empty?
373 373 User.current = user
374 374 assert Project.new.allowed_parents.compact.empty?
375 375 end
376 376
377 377 def test_allowed_parents_with_add_subprojects_permission
378 378 Role.find(1).remove_permission!(:add_project)
379 379 Role.find(1).add_permission!(:add_subprojects)
380 380 User.current = User.find(2)
381 381 # new project
382 382 assert !Project.new.allowed_parents.include?(nil)
383 383 assert Project.new.allowed_parents.include?(Project.find(1))
384 384 # existing root project
385 385 assert Project.find(1).allowed_parents.include?(nil)
386 386 # existing child
387 387 assert Project.find(3).allowed_parents.include?(Project.find(1))
388 388 assert !Project.find(3).allowed_parents.include?(nil)
389 389 end
390 390
391 391 def test_allowed_parents_with_add_project_permission
392 392 Role.find(1).add_permission!(:add_project)
393 393 Role.find(1).remove_permission!(:add_subprojects)
394 394 User.current = User.find(2)
395 395 # new project
396 396 assert Project.new.allowed_parents.include?(nil)
397 397 assert !Project.new.allowed_parents.include?(Project.find(1))
398 398 # existing root project
399 399 assert Project.find(1).allowed_parents.include?(nil)
400 400 # existing child
401 401 assert Project.find(3).allowed_parents.include?(Project.find(1))
402 402 assert Project.find(3).allowed_parents.include?(nil)
403 403 end
404 404
405 405 def test_allowed_parents_with_add_project_and_subprojects_permission
406 406 Role.find(1).add_permission!(:add_project)
407 407 Role.find(1).add_permission!(:add_subprojects)
408 408 User.current = User.find(2)
409 409 # new project
410 410 assert Project.new.allowed_parents.include?(nil)
411 411 assert Project.new.allowed_parents.include?(Project.find(1))
412 412 # existing root project
413 413 assert Project.find(1).allowed_parents.include?(nil)
414 414 # existing child
415 415 assert Project.find(3).allowed_parents.include?(Project.find(1))
416 416 assert Project.find(3).allowed_parents.include?(nil)
417 417 end
418 418
419 419 def test_users_by_role
420 420 users_by_role = Project.find(1).users_by_role
421 421 assert_kind_of Hash, users_by_role
422 422 role = Role.find(1)
423 423 assert_kind_of Array, users_by_role[role]
424 424 assert users_by_role[role].include?(User.find(2))
425 425 end
426 426
427 427 def test_rolled_up_trackers
428 428 parent = Project.find(1)
429 429 parent.trackers = Tracker.find([1,2])
430 430 child = parent.children.find(3)
431 431
432 432 assert_equal [1, 2], parent.tracker_ids
433 433 assert_equal [2, 3], child.trackers.collect(&:id)
434 434
435 435 assert_kind_of Tracker, parent.rolled_up_trackers.first
436 436 assert_equal Tracker.find(1), parent.rolled_up_trackers.first
437 437
438 438 assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id)
439 439 assert_equal [2, 3], child.rolled_up_trackers.collect(&:id)
440 440 end
441 441
442 442 def test_rolled_up_trackers_should_ignore_archived_subprojects
443 443 parent = Project.find(1)
444 444 parent.trackers = Tracker.find([1,2])
445 445 child = parent.children.find(3)
446 446 child.trackers = Tracker.find([1,3])
447 447 parent.children.each(&:archive)
448 448
449 449 assert_equal [1,2], parent.rolled_up_trackers.collect(&:id)
450 450 end
451 451
452 452 context "#rolled_up_versions" do
453 453 setup do
454 454 @project = Project.generate!
455 455 @parent_version_1 = Version.generate!(:project => @project)
456 456 @parent_version_2 = Version.generate!(:project => @project)
457 457 end
458 458
459 459 should "include the versions for the current project" do
460 460 assert_same_elements [@parent_version_1, @parent_version_2], @project.rolled_up_versions
461 461 end
462 462
463 463 should "include versions for a subproject" do
464 464 @subproject = Project.generate!
465 465 @subproject.set_parent!(@project)
466 466 @subproject_version = Version.generate!(:project => @subproject)
467 467
468 468 assert_same_elements [
469 469 @parent_version_1,
470 470 @parent_version_2,
471 471 @subproject_version
472 472 ], @project.rolled_up_versions
473 473 end
474 474
475 475 should "include versions for a sub-subproject" do
476 476 @subproject = Project.generate!
477 477 @subproject.set_parent!(@project)
478 478 @sub_subproject = Project.generate!
479 479 @sub_subproject.set_parent!(@subproject)
480 480 @sub_subproject_version = Version.generate!(:project => @sub_subproject)
481 481
482 482 @project.reload
483 483
484 484 assert_same_elements [
485 485 @parent_version_1,
486 486 @parent_version_2,
487 487 @sub_subproject_version
488 488 ], @project.rolled_up_versions
489 489 end
490 490
491 491 should "only check active projects" do
492 492 @subproject = Project.generate!
493 493 @subproject.set_parent!(@project)
494 494 @subproject_version = Version.generate!(:project => @subproject)
495 495 assert @subproject.archive
496 496
497 497 @project.reload
498 498
499 499 assert !@subproject.active?
500 500 assert_same_elements [@parent_version_1, @parent_version_2], @project.rolled_up_versions
501 501 end
502 502 end
503 503
504 504 def test_shared_versions_none_sharing
505 505 p = Project.find(5)
506 506 v = Version.create!(:name => 'none_sharing', :project => p, :sharing => 'none')
507 507 assert p.shared_versions.include?(v)
508 508 assert !p.children.first.shared_versions.include?(v)
509 509 assert !p.root.shared_versions.include?(v)
510 510 assert !p.siblings.first.shared_versions.include?(v)
511 511 assert !p.root.siblings.first.shared_versions.include?(v)
512 512 end
513 513
514 514 def test_shared_versions_descendants_sharing
515 515 p = Project.find(5)
516 516 v = Version.create!(:name => 'descendants_sharing', :project => p, :sharing => 'descendants')
517 517 assert p.shared_versions.include?(v)
518 518 assert p.children.first.shared_versions.include?(v)
519 519 assert !p.root.shared_versions.include?(v)
520 520 assert !p.siblings.first.shared_versions.include?(v)
521 521 assert !p.root.siblings.first.shared_versions.include?(v)
522 522 end
523 523
524 524 def test_shared_versions_hierarchy_sharing
525 525 p = Project.find(5)
526 526 v = Version.create!(:name => 'hierarchy_sharing', :project => p, :sharing => 'hierarchy')
527 527 assert p.shared_versions.include?(v)
528 528 assert p.children.first.shared_versions.include?(v)
529 529 assert p.root.shared_versions.include?(v)
530 530 assert !p.siblings.first.shared_versions.include?(v)
531 531 assert !p.root.siblings.first.shared_versions.include?(v)
532 532 end
533 533
534 534 def test_shared_versions_tree_sharing
535 535 p = Project.find(5)
536 536 v = Version.create!(:name => 'tree_sharing', :project => p, :sharing => 'tree')
537 537 assert p.shared_versions.include?(v)
538 538 assert p.children.first.shared_versions.include?(v)
539 539 assert p.root.shared_versions.include?(v)
540 540 assert p.siblings.first.shared_versions.include?(v)
541 541 assert !p.root.siblings.first.shared_versions.include?(v)
542 542 end
543 543
544 544 def test_shared_versions_system_sharing
545 545 p = Project.find(5)
546 546 v = Version.create!(:name => 'system_sharing', :project => p, :sharing => 'system')
547 547 assert p.shared_versions.include?(v)
548 548 assert p.children.first.shared_versions.include?(v)
549 549 assert p.root.shared_versions.include?(v)
550 550 assert p.siblings.first.shared_versions.include?(v)
551 551 assert p.root.siblings.first.shared_versions.include?(v)
552 552 end
553 553
554 554 def test_shared_versions
555 555 parent = Project.find(1)
556 556 child = parent.children.find(3)
557 557 private_child = parent.children.find(5)
558 558
559 559 assert_equal [1,2,3], parent.version_ids.sort
560 560 assert_equal [4], child.version_ids
561 561 assert_equal [6], private_child.version_ids
562 562 assert_equal [7], Version.find_all_by_sharing('system').collect(&:id)
563 563
564 564 assert_equal 6, parent.shared_versions.size
565 565 parent.shared_versions.each do |version|
566 566 assert_kind_of Version, version
567 567 end
568 568
569 569 assert_equal [1,2,3,4,6,7], parent.shared_versions.collect(&:id).sort
570 570 end
571 571
572 572 def test_shared_versions_should_ignore_archived_subprojects
573 573 parent = Project.find(1)
574 574 child = parent.children.find(3)
575 575 child.archive
576 576 parent.reload
577 577
578 578 assert_equal [1,2,3], parent.version_ids.sort
579 579 assert_equal [4], child.version_ids
580 580 assert !parent.shared_versions.collect(&:id).include?(4)
581 581 end
582 582
583 583 def test_shared_versions_visible_to_user
584 584 user = User.find(3)
585 585 parent = Project.find(1)
586 586 child = parent.children.find(5)
587 587
588 588 assert_equal [1,2,3], parent.version_ids.sort
589 589 assert_equal [6], child.version_ids
590 590
591 591 versions = parent.shared_versions.visible(user)
592 592
593 593 assert_equal 4, versions.size
594 594 versions.each do |version|
595 595 assert_kind_of Version, version
596 596 end
597 597
598 598 assert !versions.collect(&:id).include?(6)
599 599 end
600 600
601 601 def test_shared_versions_for_new_project_should_include_system_shared_versions
602 602 p = Project.find(5)
603 603 v = Version.create!(:name => 'system_sharing', :project => p, :sharing => 'system')
604 604
605 605 assert_include v, Project.new.shared_versions
606 606 end
607 607
608 608 def test_next_identifier
609 609 ProjectCustomField.delete_all
610 610 Project.create!(:name => 'last', :identifier => 'p2008040')
611 611 assert_equal 'p2008041', Project.next_identifier
612 612 end
613 613
614 614 def test_next_identifier_first_project
615 615 Project.delete_all
616 616 assert_nil Project.next_identifier
617 617 end
618 618
619 619 def test_enabled_module_names
620 620 with_settings :default_projects_modules => ['issue_tracking', 'repository'] do
621 621 project = Project.new
622 622
623 623 project.enabled_module_names = %w(issue_tracking news)
624 624 assert_equal %w(issue_tracking news), project.enabled_module_names.sort
625 625 end
626 626 end
627 627
628 628 context "enabled_modules" do
629 629 setup do
630 630 @project = Project.find(1)
631 631 end
632 632
633 633 should "define module by names and preserve ids" do
634 634 # Remove one module
635 635 modules = @project.enabled_modules.slice(0..-2)
636 636 assert modules.any?
637 637 assert_difference 'EnabledModule.count', -1 do
638 638 @project.enabled_module_names = modules.collect(&:name)
639 639 end
640 640 @project.reload
641 641 # Ids should be preserved
642 642 assert_equal @project.enabled_module_ids.sort, modules.collect(&:id).sort
643 643 end
644 644
645 645 should "enable a module" do
646 646 @project.enabled_module_names = []
647 647 @project.reload
648 648 assert_equal [], @project.enabled_module_names
649 649 #with string
650 650 @project.enable_module!("issue_tracking")
651 651 assert_equal ["issue_tracking"], @project.enabled_module_names
652 652 #with symbol
653 653 @project.enable_module!(:gantt)
654 654 assert_equal ["issue_tracking", "gantt"], @project.enabled_module_names
655 655 #don't add a module twice
656 656 @project.enable_module!("issue_tracking")
657 657 assert_equal ["issue_tracking", "gantt"], @project.enabled_module_names
658 658 end
659 659
660 660 should "disable a module" do
661 661 #with string
662 662 assert @project.enabled_module_names.include?("issue_tracking")
663 663 @project.disable_module!("issue_tracking")
664 664 assert ! @project.reload.enabled_module_names.include?("issue_tracking")
665 665 #with symbol
666 666 assert @project.enabled_module_names.include?("gantt")
667 667 @project.disable_module!(:gantt)
668 668 assert ! @project.reload.enabled_module_names.include?("gantt")
669 669 #with EnabledModule object
670 670 first_module = @project.enabled_modules.first
671 671 @project.disable_module!(first_module)
672 672 assert ! @project.reload.enabled_module_names.include?(first_module.name)
673 673 end
674 674 end
675 675
676 676 def test_enabled_module_names_should_not_recreate_enabled_modules
677 677 project = Project.find(1)
678 678 # Remove one module
679 679 modules = project.enabled_modules.slice(0..-2)
680 680 assert modules.any?
681 681 assert_difference 'EnabledModule.count', -1 do
682 682 project.enabled_module_names = modules.collect(&:name)
683 683 end
684 684 project.reload
685 685 # Ids should be preserved
686 686 assert_equal project.enabled_module_ids.sort, modules.collect(&:id).sort
687 687 end
688 688
689 689 def test_copy_from_existing_project
690 690 source_project = Project.find(1)
691 691 copied_project = Project.copy_from(1)
692 692
693 693 assert copied_project
694 694 # Cleared attributes
695 695 assert copied_project.id.blank?
696 696 assert copied_project.name.blank?
697 697 assert copied_project.identifier.blank?
698 698
699 699 # Duplicated attributes
700 700 assert_equal source_project.description, copied_project.description
701 701 assert_equal source_project.enabled_modules, copied_project.enabled_modules
702 702 assert_equal source_project.trackers, copied_project.trackers
703 703
704 704 # Default attributes
705 705 assert_equal 1, copied_project.status
706 706 end
707 707
708 708 def test_activities_should_use_the_system_activities
709 709 project = Project.find(1)
710 710 assert_equal project.activities, TimeEntryActivity.find(:all, :conditions => {:active => true} )
711 711 end
712 712
713 713
714 714 def test_activities_should_use_the_project_specific_activities
715 715 project = Project.find(1)
716 716 overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project})
717 717 assert overridden_activity.save!
718 718
719 719 assert project.activities.include?(overridden_activity), "Project specific Activity not found"
720 720 end
721 721
722 722 def test_activities_should_not_include_the_inactive_project_specific_activities
723 723 project = Project.find(1)
724 724 overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project, :parent => TimeEntryActivity.find(:first), :active => false})
725 725 assert overridden_activity.save!
726 726
727 727 assert !project.activities.include?(overridden_activity), "Inactive Project specific Activity found"
728 728 end
729 729
730 730 def test_activities_should_not_include_project_specific_activities_from_other_projects
731 731 project = Project.find(1)
732 732 overridden_activity = TimeEntryActivity.new({:name => "Project", :project => Project.find(2)})
733 733 assert overridden_activity.save!
734 734
735 735 assert !project.activities.include?(overridden_activity), "Project specific Activity found on a different project"
736 736 end
737 737
738 738 def test_activities_should_handle_nils
739 739 overridden_activity = TimeEntryActivity.new({:name => "Project", :project => Project.find(1), :parent => TimeEntryActivity.find(:first)})
740 740 TimeEntryActivity.delete_all
741 741
742 742 # No activities
743 743 project = Project.find(1)
744 744 assert project.activities.empty?
745 745
746 746 # No system, one overridden
747 747 assert overridden_activity.save!
748 748 project.reload
749 749 assert_equal [overridden_activity], project.activities
750 750 end
751 751
752 752 def test_activities_should_override_system_activities_with_project_activities
753 753 project = Project.find(1)
754 754 parent_activity = TimeEntryActivity.find(:first)
755 755 overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project, :parent => parent_activity})
756 756 assert overridden_activity.save!
757 757
758 758 assert project.activities.include?(overridden_activity), "Project specific Activity not found"
759 759 assert !project.activities.include?(parent_activity), "System Activity found when it should have been overridden"
760 760 end
761 761
762 762 def test_activities_should_include_inactive_activities_if_specified
763 763 project = Project.find(1)
764 764 overridden_activity = TimeEntryActivity.new({:name => "Project", :project => project, :parent => TimeEntryActivity.find(:first), :active => false})
765 765 assert overridden_activity.save!
766 766
767 767 assert project.activities(true).include?(overridden_activity), "Inactive Project specific Activity not found"
768 768 end
769 769
770 770 test 'activities should not include active System activities if the project has an override that is inactive' do
771 771 project = Project.find(1)
772 772 system_activity = TimeEntryActivity.find_by_name('Design')
773 773 assert system_activity.active?
774 774 overridden_activity = TimeEntryActivity.generate!(:project => project, :parent => system_activity, :active => false)
775 775 assert overridden_activity.save!
776 776
777 777 assert !project.activities.include?(overridden_activity), "Inactive Project specific Activity not found"
778 778 assert !project.activities.include?(system_activity), "System activity found when the project has an inactive override"
779 779 end
780 780
781 781 def test_close_completed_versions
782 782 Version.update_all("status = 'open'")
783 783 project = Project.find(1)
784 784 assert_not_nil project.versions.detect {|v| v.completed? && v.status == 'open'}
785 785 assert_not_nil project.versions.detect {|v| !v.completed? && v.status == 'open'}
786 786 project.close_completed_versions
787 787 project.reload
788 788 assert_nil project.versions.detect {|v| v.completed? && v.status != 'closed'}
789 789 assert_not_nil project.versions.detect {|v| !v.completed? && v.status == 'open'}
790 790 end
791 791
792 792 context "Project#copy" do
793 793 setup do
794 794 ProjectCustomField.destroy_all # Custom values are a mess to isolate in tests
795 795 Project.destroy_all :identifier => "copy-test"
796 796 @source_project = Project.find(2)
797 797 @project = Project.new(:name => 'Copy Test', :identifier => 'copy-test')
798 798 @project.trackers = @source_project.trackers
799 799 @project.enabled_module_names = @source_project.enabled_modules.collect(&:name)
800 800 end
801 801
802 802 should "copy issues" do
803 803 @source_project.issues << Issue.generate!(:status => IssueStatus.find_by_name('Closed'),
804 804 :subject => "copy issue status",
805 805 :tracker_id => 1,
806 806 :assigned_to_id => 2,
807 807 :project_id => @source_project.id)
808 808 assert @project.valid?
809 809 assert @project.issues.empty?
810 810 assert @project.copy(@source_project)
811 811
812 812 assert_equal @source_project.issues.size, @project.issues.size
813 813 @project.issues.each do |issue|
814 814 assert issue.valid?
815 815 assert ! issue.assigned_to.blank?
816 816 assert_equal @project, issue.project
817 817 end
818 818
819 819 copied_issue = @project.issues.first(:conditions => {:subject => "copy issue status"})
820 820 assert copied_issue
821 821 assert copied_issue.status
822 822 assert_equal "Closed", copied_issue.status.name
823 823 end
824 824
825 825 should "change the new issues to use the copied version" do
826 826 User.current = User.find(1)
827 827 assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open')
828 828 @source_project.versions << assigned_version
829 829 assert_equal 3, @source_project.versions.size
830 830 Issue.generate_for_project!(@source_project,
831 831 :fixed_version_id => assigned_version.id,
832 832 :subject => "change the new issues to use the copied version",
833 833 :tracker_id => 1,
834 834 :project_id => @source_project.id)
835 835
836 836 assert @project.copy(@source_project)
837 837 @project.reload
838 838 copied_issue = @project.issues.first(:conditions => {:subject => "change the new issues to use the copied version"})
839 839
840 840 assert copied_issue
841 841 assert copied_issue.fixed_version
842 842 assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name
843 843 assert_not_equal assigned_version.id, copied_issue.fixed_version.id # Different record
844 844 end
845 845
846 846 should "copy issue relations" do
847 847 Setting.cross_project_issue_relations = '1'
848 848
849 849 second_issue = Issue.generate!(:status_id => 5,
850 850 :subject => "copy issue relation",
851 851 :tracker_id => 1,
852 852 :assigned_to_id => 2,
853 853 :project_id => @source_project.id)
854 854 source_relation = IssueRelation.generate!(:issue_from => Issue.find(4),
855 855 :issue_to => second_issue,
856 856 :relation_type => "relates")
857 857 source_relation_cross_project = IssueRelation.generate!(:issue_from => Issue.find(1),
858 858 :issue_to => second_issue,
859 859 :relation_type => "duplicates")
860 860
861 861 assert @project.copy(@source_project)
862 862 assert_equal @source_project.issues.count, @project.issues.count
863 863 copied_issue = @project.issues.find_by_subject("Issue on project 2") # Was #4
864 864 copied_second_issue = @project.issues.find_by_subject("copy issue relation")
865 865
866 866 # First issue with a relation on project
867 867 assert_equal 1, copied_issue.relations.size, "Relation not copied"
868 868 copied_relation = copied_issue.relations.first
869 869 assert_equal "relates", copied_relation.relation_type
870 870 assert_equal copied_second_issue.id, copied_relation.issue_to_id
871 871 assert_not_equal source_relation.id, copied_relation.id
872 872
873 873 # Second issue with a cross project relation
874 874 assert_equal 2, copied_second_issue.relations.size, "Relation not copied"
875 875 copied_relation = copied_second_issue.relations.select {|r| r.relation_type == 'duplicates'}.first
876 876 assert_equal "duplicates", copied_relation.relation_type
877 877 assert_equal 1, copied_relation.issue_from_id, "Cross project relation not kept"
878 878 assert_not_equal source_relation_cross_project.id, copied_relation.id
879 879 end
880 880
881 881 should "copy issue attachments" do
882 882 issue = Issue.generate!(:subject => "copy with attachment", :tracker_id => 1, :project_id => @source_project.id)
883 883 Attachment.create!(:container => issue, :file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 1)
884 884 @source_project.issues << issue
885 885 assert @project.copy(@source_project)
886 886
887 887 copied_issue = @project.issues.first(:conditions => {:subject => "copy with attachment"})
888 888 assert_not_nil copied_issue
889 889 assert_equal 1, copied_issue.attachments.count, "Attachment not copied"
890 890 assert_equal "testfile.txt", copied_issue.attachments.first.filename
891 891 end
892 892
893 893 should "copy memberships" do
894 894 assert @project.valid?
895 895 assert @project.members.empty?
896 896 assert @project.copy(@source_project)
897 897
898 898 assert_equal @source_project.memberships.size, @project.memberships.size
899 899 @project.memberships.each do |membership|
900 900 assert membership
901 901 assert_equal @project, membership.project
902 902 end
903 903 end
904 904
905 905 should "copy memberships with groups and additional roles" do
906 906 group = Group.create!(:lastname => "Copy group")
907 907 user = User.find(7)
908 908 group.users << user
909 909 # group role
910 910 Member.create!(:project_id => @source_project.id, :principal => group, :role_ids => [2])
911 911 member = Member.find_by_user_id_and_project_id(user.id, @source_project.id)
912 912 # additional role
913 913 member.role_ids = [1]
914 914
915 915 assert @project.copy(@source_project)
916 916 member = Member.find_by_user_id_and_project_id(user.id, @project.id)
917 917 assert_not_nil member
918 918 assert_equal [1, 2], member.role_ids.sort
919 919 end
920 920
921 921 should "copy project specific queries" do
922 922 assert @project.valid?
923 923 assert @project.queries.empty?
924 924 assert @project.copy(@source_project)
925 925
926 926 assert_equal @source_project.queries.size, @project.queries.size
927 927 @project.queries.each do |query|
928 928 assert query
929 929 assert_equal @project, query.project
930 930 end
931 931 assert_equal @source_project.queries.map(&:user_id).sort, @project.queries.map(&:user_id).sort
932 932 end
933 933
934 934 should "copy versions" do
935 935 @source_project.versions << Version.generate!
936 936 @source_project.versions << Version.generate!
937 937
938 938 assert @project.versions.empty?
939 939 assert @project.copy(@source_project)
940 940
941 941 assert_equal @source_project.versions.size, @project.versions.size
942 942 @project.versions.each do |version|
943 943 assert version
944 944 assert_equal @project, version.project
945 945 end
946 946 end
947 947
948 948 should "copy wiki" do
949 949 assert_difference 'Wiki.count' do
950 950 assert @project.copy(@source_project)
951 951 end
952 952
953 953 assert @project.wiki
954 954 assert_not_equal @source_project.wiki, @project.wiki
955 955 assert_equal "Start page", @project.wiki.start_page
956 956 end
957 957
958 958 should "copy wiki pages and content with hierarchy" do
959 959 assert_difference 'WikiPage.count', @source_project.wiki.pages.size do
960 960 assert @project.copy(@source_project)
961 961 end
962 962
963 963 assert @project.wiki
964 964 assert_equal @source_project.wiki.pages.size, @project.wiki.pages.size
965 965
966 966 @project.wiki.pages.each do |wiki_page|
967 967 assert wiki_page.content
968 968 assert !@source_project.wiki.pages.include?(wiki_page)
969 969 end
970 970
971 971 parent = @project.wiki.find_page('Parent_page')
972 972 child1 = @project.wiki.find_page('Child_page_1')
973 973 child2 = @project.wiki.find_page('Child_page_2')
974 974 assert_equal parent, child1.parent
975 975 assert_equal parent, child2.parent
976 976 end
977 977
978 978 should "copy issue categories" do
979 979 assert @project.copy(@source_project)
980 980
981 981 assert_equal 2, @project.issue_categories.size
982 982 @project.issue_categories.each do |issue_category|
983 983 assert !@source_project.issue_categories.include?(issue_category)
984 984 end
985 985 end
986 986
987 987 should "copy boards" do
988 988 assert @project.copy(@source_project)
989 989
990 990 assert_equal 1, @project.boards.size
991 991 @project.boards.each do |board|
992 992 assert !@source_project.boards.include?(board)
993 993 end
994 994 end
995 995
996 996 should "change the new issues to use the copied issue categories" do
997 997 issue = Issue.find(4)
998 998 issue.update_attribute(:category_id, 3)
999 999
1000 1000 assert @project.copy(@source_project)
1001 1001
1002 1002 @project.issues.each do |issue|
1003 1003 assert issue.category
1004 1004 assert_equal "Stock management", issue.category.name # Same name
1005 1005 assert_not_equal IssueCategory.find(3), issue.category # Different record
1006 1006 end
1007 1007 end
1008 1008
1009 1009 should "limit copy with :only option" do
1010 1010 assert @project.members.empty?
1011 1011 assert @project.issue_categories.empty?
1012 1012 assert @source_project.issues.any?
1013 1013
1014 1014 assert @project.copy(@source_project, :only => ['members', 'issue_categories'])
1015 1015
1016 1016 assert @project.members.any?
1017 1017 assert @project.issue_categories.any?
1018 1018 assert @project.issues.empty?
1019 1019 end
1020 1020
1021 1021 end
1022 1022
1023 1023 context "#start_date" do
1024 1024 setup do
1025 1025 ProjectCustomField.destroy_all # Custom values are a mess to isolate in tests
1026 1026 @project = Project.generate!(:identifier => 'test0')
1027 1027 @project.trackers << Tracker.generate!
1028 1028 end
1029 1029
1030 1030 should "be nil if there are no issues on the project" do
1031 1031 assert_nil @project.start_date
1032 1032 end
1033 1033
1034 1034 should "be tested when issues have no start date"
1035 1035
1036 1036 should "be the earliest start date of it's issues" do
1037 1037 early = 7.days.ago.to_date
1038 1038 Issue.generate_for_project!(@project, :start_date => Date.today)
1039 1039 Issue.generate_for_project!(@project, :start_date => early)
1040 1040
1041 1041 assert_equal early, @project.start_date
1042 1042 end
1043 1043
1044 1044 end
1045 1045
1046 1046 context "#due_date" do
1047 1047 setup do
1048 1048 ProjectCustomField.destroy_all # Custom values are a mess to isolate in tests
1049 1049 @project = Project.generate!(:identifier => 'test0')
1050 1050 @project.trackers << Tracker.generate!
1051 1051 end
1052 1052
1053 1053 should "be nil if there are no issues on the project" do
1054 1054 assert_nil @project.due_date
1055 1055 end
1056 1056
1057 1057 should "be tested when issues have no due date"
1058 1058
1059 1059 should "be the latest due date of it's issues" do
1060 1060 future = 7.days.from_now.to_date
1061 1061 Issue.generate_for_project!(@project, :due_date => future)
1062 1062 Issue.generate_for_project!(@project, :due_date => Date.today)
1063 1063
1064 1064 assert_equal future, @project.due_date
1065 1065 end
1066 1066
1067 1067 should "be the latest due date of it's versions" do
1068 1068 future = 7.days.from_now.to_date
1069 1069 @project.versions << Version.generate!(:effective_date => future)
1070 1070 @project.versions << Version.generate!(:effective_date => Date.today)
1071 1071
1072 1072
1073 1073 assert_equal future, @project.due_date
1074 1074
1075 1075 end
1076 1076
1077 1077 should "pick the latest date from it's issues and versions" do
1078 1078 future = 7.days.from_now.to_date
1079 1079 far_future = 14.days.from_now.to_date
1080 1080 Issue.generate_for_project!(@project, :due_date => far_future)
1081 1081 @project.versions << Version.generate!(:effective_date => future)
1082 1082
1083 1083 assert_equal far_future, @project.due_date
1084 1084 end
1085 1085
1086 1086 end
1087 1087
1088 1088 context "Project#completed_percent" do
1089 1089 setup do
1090 1090 ProjectCustomField.destroy_all # Custom values are a mess to isolate in tests
1091 1091 @project = Project.generate!(:identifier => 'test0')
1092 1092 @project.trackers << Tracker.generate!
1093 1093 end
1094 1094
1095 1095 context "no versions" do
1096 1096 should "be 100" do
1097 1097 assert_equal 100, @project.completed_percent
1098 1098 end
1099 1099 end
1100 1100
1101 1101 context "with versions" do
1102 1102 should "return 0 if the versions have no issues" do
1103 1103 Version.generate!(:project => @project)
1104 1104 Version.generate!(:project => @project)
1105 1105
1106 1106 assert_equal 0, @project.completed_percent
1107 1107 end
1108 1108
1109 1109 should "return 100 if the version has only closed issues" do
1110 1110 v1 = Version.generate!(:project => @project)
1111 1111 Issue.generate_for_project!(@project, :status => IssueStatus.find_by_name('Closed'), :fixed_version => v1)
1112 1112 v2 = Version.generate!(:project => @project)
1113 1113 Issue.generate_for_project!(@project, :status => IssueStatus.find_by_name('Closed'), :fixed_version => v2)
1114 1114
1115 1115 assert_equal 100, @project.completed_percent
1116 1116 end
1117 1117
1118 1118 should "return the averaged completed percent of the versions (not weighted)" do
1119 1119 v1 = Version.generate!(:project => @project)
1120 1120 Issue.generate_for_project!(@project, :status => IssueStatus.find_by_name('New'), :estimated_hours => 10, :done_ratio => 50, :fixed_version => v1)
1121 1121 v2 = Version.generate!(:project => @project)
1122 1122 Issue.generate_for_project!(@project, :status => IssueStatus.find_by_name('New'), :estimated_hours => 10, :done_ratio => 50, :fixed_version => v2)
1123 1123
1124 1124 assert_equal 50, @project.completed_percent
1125 1125 end
1126 1126
1127 1127 end
1128 1128 end
1129 1129
1130 1130 context "#notified_users" do
1131 1131 setup do
1132 1132 @project = Project.generate!
1133 1133 @role = Role.generate!
1134 1134
1135 1135 @user_with_membership_notification = User.generate!(:mail_notification => 'selected')
1136 1136 Member.generate!(:project => @project, :roles => [@role], :principal => @user_with_membership_notification, :mail_notification => true)
1137 1137
1138 1138 @all_events_user = User.generate!(:mail_notification => 'all')
1139 1139 Member.generate!(:project => @project, :roles => [@role], :principal => @all_events_user)
1140 1140
1141 1141 @no_events_user = User.generate!(:mail_notification => 'none')
1142 1142 Member.generate!(:project => @project, :roles => [@role], :principal => @no_events_user)
1143 1143
1144 1144 @only_my_events_user = User.generate!(:mail_notification => 'only_my_events')
1145 1145 Member.generate!(:project => @project, :roles => [@role], :principal => @only_my_events_user)
1146 1146
1147 1147 @only_assigned_user = User.generate!(:mail_notification => 'only_assigned')
1148 1148 Member.generate!(:project => @project, :roles => [@role], :principal => @only_assigned_user)
1149 1149
1150 1150 @only_owned_user = User.generate!(:mail_notification => 'only_owner')
1151 1151 Member.generate!(:project => @project, :roles => [@role], :principal => @only_owned_user)
1152 1152 end
1153 1153
1154 1154 should "include members with a mail notification" do
1155 1155 assert @project.notified_users.include?(@user_with_membership_notification)
1156 1156 end
1157 1157
1158 1158 should "include users with the 'all' notification option" do
1159 1159 assert @project.notified_users.include?(@all_events_user)
1160 1160 end
1161 1161
1162 1162 should "not include users with the 'none' notification option" do
1163 1163 assert !@project.notified_users.include?(@no_events_user)
1164 1164 end
1165 1165
1166 1166 should "not include users with the 'only_my_events' notification option" do
1167 1167 assert !@project.notified_users.include?(@only_my_events_user)
1168 1168 end
1169 1169
1170 1170 should "not include users with the 'only_assigned' notification option" do
1171 1171 assert !@project.notified_users.include?(@only_assigned_user)
1172 1172 end
1173 1173
1174 1174 should "not include users with the 'only_owner' notification option" do
1175 1175 assert !@project.notified_users.include?(@only_owned_user)
1176 1176 end
1177 1177 end
1178 1178
1179 1179 end
General Comments 0
You need to be logged in to leave comments. Login now