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