annotate test/unit/project_test.rb @ 1082:997f6d7738f7 bug_531

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