project_copy_test.rb 13.5 KB
Newer Older
jplang's avatar
jplang committed
1
# Redmine - project management software
marutosijp's avatar
marutosijp committed
2
# Copyright (C) 2006-2014  Jean-Philippe Lang
jplang's avatar
jplang committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

require File.expand_path('../../test_helper', __FILE__)

class ProjectCopyTest < ActiveSupport::TestCase
  fixtures :projects, :trackers, :issue_statuses, :issues,
           :journals, :journal_details,
           :enumerations, :users, :issue_categories,
           :projects_trackers,
           :custom_fields,
           :custom_fields_projects,
           :custom_fields_trackers,
           :custom_values,
           :roles,
           :member_roles,
           :members,
           :enabled_modules,
           :versions,
           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
           :groups_users,
           :boards, :messages,
           :repositories,
           :news, :comments,
           :documents

  def setup
    ProjectCustomField.destroy_all
    @source_project = Project.find(2)
    @project = Project.new(:name => 'Copy Test', :identifier => 'copy-test')
    @project.trackers = @source_project.trackers
    @project.enabled_module_names = @source_project.enabled_modules.collect(&:name)
  end

  test "#copy should copy issues" do
    @source_project.issues << Issue.generate!(:status => IssueStatus.find_by_name('Closed'),
                                              :subject => "copy issue status",
                                              :tracker_id => 1,
                                              :assigned_to_id => 2,
                                              :project_id => @source_project.id)
    assert @project.valid?
    assert @project.issues.empty?
    assert @project.copy(@source_project)

    assert_equal @source_project.issues.size, @project.issues.size
    @project.issues.each do |issue|
      assert issue.valid?
      assert ! issue.assigned_to.blank?
      assert_equal @project, issue.project
    end

66
    copied_issue = @project.issues.where(:subject => "copy issue status").first
jplang's avatar
jplang committed
67 68 69 70 71
    assert copied_issue
    assert copied_issue.status
    assert_equal "Closed", copied_issue.status.name
  end

72 73 74 75 76 77 78 79 80 81 82 83 84
  test "#copy should copy issues custom values" do
    field = IssueCustomField.generate!(:is_for_all => true, :trackers => Tracker.all)
    issue = Issue.generate!(:project => @source_project, :subject => 'Custom field copy')
    issue.custom_field_values = {field.id => 'custom'}
    issue.save!
    assert_equal 'custom', issue.reload.custom_field_value(field)

    assert @project.copy(@source_project)
    copy = @project.issues.find_by_subject('Custom field copy')
    assert copy
    assert_equal 'custom', copy.reload.custom_field_value(field)
  end

jplang's avatar
jplang committed
85 86 87 88 89 90 91 92 93 94 95
  test "#copy should copy issues assigned to a locked version" do
    User.current = User.find(1)
    assigned_version = Version.generate!(:name => "Assigned Issues")
    @source_project.versions << assigned_version
    Issue.generate!(:project => @source_project,
                    :fixed_version_id => assigned_version.id,
                    :subject => "copy issues assigned to a locked version")
    assigned_version.update_attribute :status, 'locked'

    assert @project.copy(@source_project)
    @project.reload
96
    copied_issue = @project.issues.where(:subject => "copy issues assigned to a locked version").first
jplang's avatar
jplang committed
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114

    assert copied_issue
    assert copied_issue.fixed_version
    assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name
    assert_equal 'locked', copied_issue.fixed_version.status
  end

  test "#copy should change the new issues to use the copied version" do
    User.current = User.find(1)
    assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open')
    @source_project.versions << assigned_version
    assert_equal 3, @source_project.versions.size
    Issue.generate!(:project => @source_project,
                    :fixed_version_id => assigned_version.id,
                    :subject => "change the new issues to use the copied version")

    assert @project.copy(@source_project)
    @project.reload
115
    copied_issue = @project.issues.where(:subject => "change the new issues to use the copied version").first
jplang's avatar
jplang committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

    assert copied_issue
    assert copied_issue.fixed_version
    assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name
    assert_not_equal assigned_version.id, copied_issue.fixed_version.id # Different record
  end

  test "#copy should keep target shared versions from other project" do
    assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open', :project_id => 1, :sharing => 'system')
    issue = Issue.generate!(:project => @source_project,
                            :fixed_version => assigned_version,
                            :subject => "keep target shared versions")

    assert @project.copy(@source_project)
    @project.reload
131
    copied_issue = @project.issues.where(:subject => "keep target shared versions").first
jplang's avatar
jplang committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

    assert copied_issue
    assert_equal assigned_version, copied_issue.fixed_version
  end

  test "#copy should copy issue relations" do
    Setting.cross_project_issue_relations = '1'

    second_issue = Issue.generate!(:status_id => 5,
                                   :subject => "copy issue relation",
                                   :tracker_id => 1,
                                   :assigned_to_id => 2,
                                   :project_id => @source_project.id)
    source_relation = IssueRelation.create!(:issue_from => Issue.find(4),
                                              :issue_to => second_issue,
                                              :relation_type => "relates")
    source_relation_cross_project = IssueRelation.create!(:issue_from => Issue.find(1),
                                                            :issue_to => second_issue,
                                                            :relation_type => "duplicates")

    assert @project.copy(@source_project)
    assert_equal @source_project.issues.count, @project.issues.count
    copied_issue = @project.issues.find_by_subject("Issue on project 2") # Was #4
    copied_second_issue = @project.issues.find_by_subject("copy issue relation")

    # First issue with a relation on project
    assert_equal 1, copied_issue.relations.size, "Relation not copied"
    copied_relation = copied_issue.relations.first
    assert_equal "relates", copied_relation.relation_type
    assert_equal copied_second_issue.id, copied_relation.issue_to_id
    assert_not_equal source_relation.id, copied_relation.id

    # Second issue with a cross project relation
    assert_equal 2, copied_second_issue.relations.size, "Relation not copied"
    copied_relation = copied_second_issue.relations.select {|r| r.relation_type == 'duplicates'}.first
    assert_equal "duplicates", copied_relation.relation_type
    assert_equal 1, copied_relation.issue_from_id, "Cross project relation not kept"
    assert_not_equal source_relation_cross_project.id, copied_relation.id
  end

  test "#copy should copy issue attachments" do
    issue = Issue.generate!(:subject => "copy with attachment", :tracker_id => 1, :project_id => @source_project.id)
    Attachment.create!(:container => issue, :file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 1)
    @source_project.issues << issue
    assert @project.copy(@source_project)

178
    copied_issue = @project.issues.where(:subject => "copy with attachment").first
jplang's avatar
jplang committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
    assert_not_nil copied_issue
    assert_equal 1, copied_issue.attachments.count, "Attachment not copied"
    assert_equal "testfile.txt", copied_issue.attachments.first.filename
  end

  test "#copy should copy memberships" do
    assert @project.valid?
    assert @project.members.empty?
    assert @project.copy(@source_project)

    assert_equal @source_project.memberships.size, @project.memberships.size
    @project.memberships.each do |membership|
      assert membership
      assert_equal @project, membership.project
    end
  end

  test "#copy should copy memberships with groups and additional roles" do
    group = Group.create!(:lastname => "Copy group")
    user = User.find(7)
    group.users << user
    # group role
    Member.create!(:project_id => @source_project.id, :principal => group, :role_ids => [2])
    member = Member.find_by_user_id_and_project_id(user.id, @source_project.id)
    # additional role
    member.role_ids = [1]

    assert @project.copy(@source_project)
    member = Member.find_by_user_id_and_project_id(user.id, @project.id)
    assert_not_nil member
    assert_equal [1, 2], member.role_ids.sort
  end

  test "#copy should copy project specific queries" do
    assert @project.valid?
    assert @project.queries.empty?
    assert @project.copy(@source_project)

    assert_equal @source_project.queries.size, @project.queries.size
    @project.queries.each do |query|
      assert query
      assert_equal @project, query.project
    end
    assert_equal @source_project.queries.map(&:user_id).sort, @project.queries.map(&:user_id).sort
  end

225 226 227 228 229 230 231 232 233 234 235
  def test_copy_should_copy_queries_roles_visibility
    source = Project.generate!
    target = Project.new(:name => 'Copy Test', :identifier => 'copy-test')
    IssueQuery.generate!(:project => source, :visibility => Query::VISIBILITY_ROLES, :roles => Role.where(:id => [1, 3]).to_a)

    assert target.copy(source)
    assert_equal 1, target.queries.size
    query = target.queries.first
    assert_equal [1, 3], query.role_ids.sort
  end

jplang's avatar
jplang committed
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
  test "#copy should copy versions" do
    @source_project.versions << Version.generate!
    @source_project.versions << Version.generate!

    assert @project.versions.empty?
    assert @project.copy(@source_project)

    assert_equal @source_project.versions.size, @project.versions.size
    @project.versions.each do |version|
      assert version
      assert_equal @project, version.project
    end
  end

  test "#copy should copy wiki" do
    assert_difference 'Wiki.count' do
      assert @project.copy(@source_project)
    end

    assert @project.wiki
    assert_not_equal @source_project.wiki, @project.wiki
    assert_equal "Start page", @project.wiki.start_page
  end

260 261 262 263 264 265 266 267 268
  test "#copy should copy wiki without wiki module" do
    project = Project.new(:name => 'Copy Test', :identifier => 'copy-test', :enabled_module_names => [])
    assert_difference 'Wiki.count' do
      assert project.copy(@source_project)
    end

    assert project.wiki
  end

jplang's avatar
jplang committed
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
  test "#copy should copy wiki pages and content with hierarchy" do
    assert_difference 'WikiPage.count', @source_project.wiki.pages.size do
      assert @project.copy(@source_project)
    end

    assert @project.wiki
    assert_equal @source_project.wiki.pages.size, @project.wiki.pages.size

    @project.wiki.pages.each do |wiki_page|
      assert wiki_page.content
      assert !@source_project.wiki.pages.include?(wiki_page)
    end

    parent = @project.wiki.find_page('Parent_page')
    child1 = @project.wiki.find_page('Child_page_1')
    child2 = @project.wiki.find_page('Child_page_2')
    assert_equal parent, child1.parent
    assert_equal parent, child2.parent
  end

  test "#copy should copy issue categories" do
    assert @project.copy(@source_project)

    assert_equal 2, @project.issue_categories.size
    @project.issue_categories.each do |issue_category|
      assert !@source_project.issue_categories.include?(issue_category)
    end
  end

  test "#copy should copy boards" do
    assert @project.copy(@source_project)

    assert_equal 1, @project.boards.size
    @project.boards.each do |board|
      assert !@source_project.boards.include?(board)
    end
  end

  test "#copy should change the new issues to use the copied issue categories" do
    issue = Issue.find(4)
    issue.update_attribute(:category_id, 3)

    assert @project.copy(@source_project)

    @project.issues.each do |issue|
      assert issue.category
      assert_equal "Stock management", issue.category.name # Same name
      assert_not_equal IssueCategory.find(3), issue.category # Different record
    end
  end

  test "#copy should limit copy with :only option" do
    assert @project.members.empty?
    assert @project.issue_categories.empty?
    assert @source_project.issues.any?

    assert @project.copy(@source_project, :only => ['members', 'issue_categories'])

    assert @project.members.any?
    assert @project.issue_categories.any?
    assert @project.issues.empty?
  end

  test "#copy should copy subtasks" do
    source = Project.generate!(:tracker_ids => [1])
    issue = Issue.generate_with_descendants!(:project => source)
    project = Project.new(:name => 'Copy', :identifier => 'copy', :tracker_ids => [1])

    assert_difference 'Project.count' do
      assert_difference 'Issue.count', 1+issue.descendants.count do
        assert project.copy(source.reload)
      end
    end
    copy = Issue.where(:parent_id => nil).order("id DESC").first
    assert_equal project, copy.project
    assert_equal issue.descendants.count, copy.descendants.count
    child_copy = copy.children.detect {|c| c.subject == 'Child1'}
    assert child_copy.descendants.any?
  end
end