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