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