To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / .svn / pristine / 2b / 2b22d90c6bc0187f71e0f86b9bffc12dccfc3f03.svn-base @ 1298:4f746d8966dd
History | View | Annotate | Download (13.1 KB)
| 1 | 1295:622f24f53b42 | Chris | # Redmine - project management software |
|---|---|---|---|
| 2 | # Copyright (C) 2006-2013 Jean-Philippe Lang |
||
| 3 | # |
||
| 4 | # This program is free software; you can redistribute it and/or |
||
| 5 | # modify it under the terms of the GNU General Public License |
||
| 6 | # as published by the Free Software Foundation; either version 2 |
||
| 7 | # of the License, or (at your option) any later version. |
||
| 8 | # |
||
| 9 | # This program is distributed in the hope that it will be useful, |
||
| 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 12 | # GNU General Public License for more details. |
||
| 13 | # |
||
| 14 | # You should have received a copy of the GNU General Public License |
||
| 15 | # along with this program; if not, write to the Free Software |
||
| 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||
| 17 | |||
| 18 | require File.expand_path('../../test_helper', __FILE__)
|
||
| 19 | |||
| 20 | class ProjectCopyTest < ActiveSupport::TestCase |
||
| 21 | fixtures :projects, :trackers, :issue_statuses, :issues, |
||
| 22 | :journals, :journal_details, |
||
| 23 | :enumerations, :users, :issue_categories, |
||
| 24 | :projects_trackers, |
||
| 25 | :custom_fields, |
||
| 26 | :custom_fields_projects, |
||
| 27 | :custom_fields_trackers, |
||
| 28 | :custom_values, |
||
| 29 | :roles, |
||
| 30 | :member_roles, |
||
| 31 | :members, |
||
| 32 | :enabled_modules, |
||
| 33 | :versions, |
||
| 34 | :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, |
||
| 35 | :groups_users, |
||
| 36 | :boards, :messages, |
||
| 37 | :repositories, |
||
| 38 | :news, :comments, |
||
| 39 | :documents |
||
| 40 | |||
| 41 | def setup |
||
| 42 | ProjectCustomField.destroy_all |
||
| 43 | @source_project = Project.find(2) |
||
| 44 | @project = Project.new(:name => 'Copy Test', :identifier => 'copy-test') |
||
| 45 | @project.trackers = @source_project.trackers |
||
| 46 | @project.enabled_module_names = @source_project.enabled_modules.collect(&:name) |
||
| 47 | end |
||
| 48 | |||
| 49 | test "#copy should copy issues" do |
||
| 50 | @source_project.issues << Issue.generate!(:status => IssueStatus.find_by_name('Closed'),
|
||
| 51 | :subject => "copy issue status", |
||
| 52 | :tracker_id => 1, |
||
| 53 | :assigned_to_id => 2, |
||
| 54 | :project_id => @source_project.id) |
||
| 55 | assert @project.valid? |
||
| 56 | assert @project.issues.empty? |
||
| 57 | assert @project.copy(@source_project) |
||
| 58 | |||
| 59 | assert_equal @source_project.issues.size, @project.issues.size |
||
| 60 | @project.issues.each do |issue| |
||
| 61 | assert issue.valid? |
||
| 62 | assert ! issue.assigned_to.blank? |
||
| 63 | assert_equal @project, issue.project |
||
| 64 | end |
||
| 65 | |||
| 66 | copied_issue = @project.issues.first(:conditions => {:subject => "copy issue status"})
|
||
| 67 | assert copied_issue |
||
| 68 | assert copied_issue.status |
||
| 69 | assert_equal "Closed", copied_issue.status.name |
||
| 70 | end |
||
| 71 | |||
| 72 | test "#copy should copy issues custom values" do |
||
| 73 | field = IssueCustomField.generate!(:is_for_all => true, :trackers => Tracker.all) |
||
| 74 | issue = Issue.generate!(:project => @source_project, :subject => 'Custom field copy') |
||
| 75 | issue.custom_field_values = {field.id => 'custom'}
|
||
| 76 | issue.save! |
||
| 77 | assert_equal 'custom', issue.reload.custom_field_value(field) |
||
| 78 | |||
| 79 | assert @project.copy(@source_project) |
||
| 80 | copy = @project.issues.find_by_subject('Custom field copy')
|
||
| 81 | assert copy |
||
| 82 | assert_equal 'custom', copy.reload.custom_field_value(field) |
||
| 83 | end |
||
| 84 | |||
| 85 | test "#copy should copy issues assigned to a locked version" do |
||
| 86 | User.current = User.find(1) |
||
| 87 | assigned_version = Version.generate!(:name => "Assigned Issues") |
||
| 88 | @source_project.versions << assigned_version |
||
| 89 | Issue.generate!(:project => @source_project, |
||
| 90 | :fixed_version_id => assigned_version.id, |
||
| 91 | :subject => "copy issues assigned to a locked version") |
||
| 92 | assigned_version.update_attribute :status, 'locked' |
||
| 93 | |||
| 94 | assert @project.copy(@source_project) |
||
| 95 | @project.reload |
||
| 96 | copied_issue = @project.issues.first(:conditions => {:subject => "copy issues assigned to a locked version"})
|
||
| 97 | |||
| 98 | assert copied_issue |
||
| 99 | assert copied_issue.fixed_version |
||
| 100 | assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name |
||
| 101 | assert_equal 'locked', copied_issue.fixed_version.status |
||
| 102 | end |
||
| 103 | |||
| 104 | test "#copy should change the new issues to use the copied version" do |
||
| 105 | User.current = User.find(1) |
||
| 106 | assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open') |
||
| 107 | @source_project.versions << assigned_version |
||
| 108 | assert_equal 3, @source_project.versions.size |
||
| 109 | Issue.generate!(:project => @source_project, |
||
| 110 | :fixed_version_id => assigned_version.id, |
||
| 111 | :subject => "change the new issues to use the copied version") |
||
| 112 | |||
| 113 | assert @project.copy(@source_project) |
||
| 114 | @project.reload |
||
| 115 | copied_issue = @project.issues.first(:conditions => {:subject => "change the new issues to use the copied version"})
|
||
| 116 | |||
| 117 | assert copied_issue |
||
| 118 | assert copied_issue.fixed_version |
||
| 119 | assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name |
||
| 120 | assert_not_equal assigned_version.id, copied_issue.fixed_version.id # Different record |
||
| 121 | end |
||
| 122 | |||
| 123 | test "#copy should keep target shared versions from other project" do |
||
| 124 | assigned_version = Version.generate!(:name => "Assigned Issues", :status => 'open', :project_id => 1, :sharing => 'system') |
||
| 125 | issue = Issue.generate!(:project => @source_project, |
||
| 126 | :fixed_version => assigned_version, |
||
| 127 | :subject => "keep target shared versions") |
||
| 128 | |||
| 129 | assert @project.copy(@source_project) |
||
| 130 | @project.reload |
||
| 131 | copied_issue = @project.issues.first(:conditions => {:subject => "keep target shared versions"})
|
||
| 132 | |||
| 133 | assert copied_issue |
||
| 134 | assert_equal assigned_version, copied_issue.fixed_version |
||
| 135 | end |
||
| 136 | |||
| 137 | test "#copy should copy issue relations" do |
||
| 138 | Setting.cross_project_issue_relations = '1' |
||
| 139 | |||
| 140 | second_issue = Issue.generate!(:status_id => 5, |
||
| 141 | :subject => "copy issue relation", |
||
| 142 | :tracker_id => 1, |
||
| 143 | :assigned_to_id => 2, |
||
| 144 | :project_id => @source_project.id) |
||
| 145 | source_relation = IssueRelation.create!(:issue_from => Issue.find(4), |
||
| 146 | :issue_to => second_issue, |
||
| 147 | :relation_type => "relates") |
||
| 148 | source_relation_cross_project = IssueRelation.create!(:issue_from => Issue.find(1), |
||
| 149 | :issue_to => second_issue, |
||
| 150 | :relation_type => "duplicates") |
||
| 151 | |||
| 152 | assert @project.copy(@source_project) |
||
| 153 | assert_equal @source_project.issues.count, @project.issues.count |
||
| 154 | copied_issue = @project.issues.find_by_subject("Issue on project 2") # Was #4
|
||
| 155 | copied_second_issue = @project.issues.find_by_subject("copy issue relation")
|
||
| 156 | |||
| 157 | # First issue with a relation on project |
||
| 158 | assert_equal 1, copied_issue.relations.size, "Relation not copied" |
||
| 159 | copied_relation = copied_issue.relations.first |
||
| 160 | assert_equal "relates", copied_relation.relation_type |
||
| 161 | assert_equal copied_second_issue.id, copied_relation.issue_to_id |
||
| 162 | assert_not_equal source_relation.id, copied_relation.id |
||
| 163 | |||
| 164 | # Second issue with a cross project relation |
||
| 165 | assert_equal 2, copied_second_issue.relations.size, "Relation not copied" |
||
| 166 | copied_relation = copied_second_issue.relations.select {|r| r.relation_type == 'duplicates'}.first
|
||
| 167 | assert_equal "duplicates", copied_relation.relation_type |
||
| 168 | assert_equal 1, copied_relation.issue_from_id, "Cross project relation not kept" |
||
| 169 | assert_not_equal source_relation_cross_project.id, copied_relation.id |
||
| 170 | end |
||
| 171 | |||
| 172 | test "#copy should copy issue attachments" do |
||
| 173 | issue = Issue.generate!(:subject => "copy with attachment", :tracker_id => 1, :project_id => @source_project.id) |
||
| 174 | Attachment.create!(:container => issue, :file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 1)
|
||
| 175 | @source_project.issues << issue |
||
| 176 | assert @project.copy(@source_project) |
||
| 177 | |||
| 178 | copied_issue = @project.issues.first(:conditions => {:subject => "copy with attachment"})
|
||
| 179 | assert_not_nil copied_issue |
||
| 180 | assert_equal 1, copied_issue.attachments.count, "Attachment not copied" |
||
| 181 | assert_equal "testfile.txt", copied_issue.attachments.first.filename |
||
| 182 | end |
||
| 183 | |||
| 184 | test "#copy should copy memberships" do |
||
| 185 | assert @project.valid? |
||
| 186 | assert @project.members.empty? |
||
| 187 | assert @project.copy(@source_project) |
||
| 188 | |||
| 189 | assert_equal @source_project.memberships.size, @project.memberships.size |
||
| 190 | @project.memberships.each do |membership| |
||
| 191 | assert membership |
||
| 192 | assert_equal @project, membership.project |
||
| 193 | end |
||
| 194 | end |
||
| 195 | |||
| 196 | test "#copy should copy memberships with groups and additional roles" do |
||
| 197 | group = Group.create!(:lastname => "Copy group") |
||
| 198 | user = User.find(7) |
||
| 199 | group.users << user |
||
| 200 | # group role |
||
| 201 | Member.create!(:project_id => @source_project.id, :principal => group, :role_ids => [2]) |
||
| 202 | member = Member.find_by_user_id_and_project_id(user.id, @source_project.id) |
||
| 203 | # additional role |
||
| 204 | member.role_ids = [1] |
||
| 205 | |||
| 206 | assert @project.copy(@source_project) |
||
| 207 | member = Member.find_by_user_id_and_project_id(user.id, @project.id) |
||
| 208 | assert_not_nil member |
||
| 209 | assert_equal [1, 2], member.role_ids.sort |
||
| 210 | end |
||
| 211 | |||
| 212 | test "#copy should copy project specific queries" do |
||
| 213 | assert @project.valid? |
||
| 214 | assert @project.queries.empty? |
||
| 215 | assert @project.copy(@source_project) |
||
| 216 | |||
| 217 | assert_equal @source_project.queries.size, @project.queries.size |
||
| 218 | @project.queries.each do |query| |
||
| 219 | assert query |
||
| 220 | assert_equal @project, query.project |
||
| 221 | end |
||
| 222 | assert_equal @source_project.queries.map(&:user_id).sort, @project.queries.map(&:user_id).sort |
||
| 223 | end |
||
| 224 | |||
| 225 | test "#copy should copy versions" do |
||
| 226 | @source_project.versions << Version.generate! |
||
| 227 | @source_project.versions << Version.generate! |
||
| 228 | |||
| 229 | assert @project.versions.empty? |
||
| 230 | assert @project.copy(@source_project) |
||
| 231 | |||
| 232 | assert_equal @source_project.versions.size, @project.versions.size |
||
| 233 | @project.versions.each do |version| |
||
| 234 | assert version |
||
| 235 | assert_equal @project, version.project |
||
| 236 | end |
||
| 237 | end |
||
| 238 | |||
| 239 | test "#copy should copy wiki" do |
||
| 240 | assert_difference 'Wiki.count' do |
||
| 241 | assert @project.copy(@source_project) |
||
| 242 | end |
||
| 243 | |||
| 244 | assert @project.wiki |
||
| 245 | assert_not_equal @source_project.wiki, @project.wiki |
||
| 246 | assert_equal "Start page", @project.wiki.start_page |
||
| 247 | end |
||
| 248 | |||
| 249 | test "#copy should copy wiki without wiki module" do |
||
| 250 | project = Project.new(:name => 'Copy Test', :identifier => 'copy-test', :enabled_module_names => []) |
||
| 251 | assert_difference 'Wiki.count' do |
||
| 252 | assert project.copy(@source_project) |
||
| 253 | end |
||
| 254 | |||
| 255 | assert project.wiki |
||
| 256 | end |
||
| 257 | |||
| 258 | test "#copy should copy wiki pages and content with hierarchy" do |
||
| 259 | assert_difference 'WikiPage.count', @source_project.wiki.pages.size do |
||
| 260 | assert @project.copy(@source_project) |
||
| 261 | end |
||
| 262 | |||
| 263 | assert @project.wiki |
||
| 264 | assert_equal @source_project.wiki.pages.size, @project.wiki.pages.size |
||
| 265 | |||
| 266 | @project.wiki.pages.each do |wiki_page| |
||
| 267 | assert wiki_page.content |
||
| 268 | assert !@source_project.wiki.pages.include?(wiki_page) |
||
| 269 | end |
||
| 270 | |||
| 271 | parent = @project.wiki.find_page('Parent_page')
|
||
| 272 | child1 = @project.wiki.find_page('Child_page_1')
|
||
| 273 | child2 = @project.wiki.find_page('Child_page_2')
|
||
| 274 | assert_equal parent, child1.parent |
||
| 275 | assert_equal parent, child2.parent |
||
| 276 | end |
||
| 277 | |||
| 278 | test "#copy should copy issue categories" do |
||
| 279 | assert @project.copy(@source_project) |
||
| 280 | |||
| 281 | assert_equal 2, @project.issue_categories.size |
||
| 282 | @project.issue_categories.each do |issue_category| |
||
| 283 | assert !@source_project.issue_categories.include?(issue_category) |
||
| 284 | end |
||
| 285 | end |
||
| 286 | |||
| 287 | test "#copy should copy boards" do |
||
| 288 | assert @project.copy(@source_project) |
||
| 289 | |||
| 290 | assert_equal 1, @project.boards.size |
||
| 291 | @project.boards.each do |board| |
||
| 292 | assert !@source_project.boards.include?(board) |
||
| 293 | end |
||
| 294 | end |
||
| 295 | |||
| 296 | test "#copy should change the new issues to use the copied issue categories" do |
||
| 297 | issue = Issue.find(4) |
||
| 298 | issue.update_attribute(:category_id, 3) |
||
| 299 | |||
| 300 | assert @project.copy(@source_project) |
||
| 301 | |||
| 302 | @project.issues.each do |issue| |
||
| 303 | assert issue.category |
||
| 304 | assert_equal "Stock management", issue.category.name # Same name |
||
| 305 | assert_not_equal IssueCategory.find(3), issue.category # Different record |
||
| 306 | end |
||
| 307 | end |
||
| 308 | |||
| 309 | test "#copy should limit copy with :only option" do |
||
| 310 | assert @project.members.empty? |
||
| 311 | assert @project.issue_categories.empty? |
||
| 312 | assert @source_project.issues.any? |
||
| 313 | |||
| 314 | assert @project.copy(@source_project, :only => ['members', 'issue_categories']) |
||
| 315 | |||
| 316 | assert @project.members.any? |
||
| 317 | assert @project.issue_categories.any? |
||
| 318 | assert @project.issues.empty? |
||
| 319 | end |
||
| 320 | |||
| 321 | test "#copy should copy subtasks" do |
||
| 322 | source = Project.generate!(:tracker_ids => [1]) |
||
| 323 | issue = Issue.generate_with_descendants!(:project => source) |
||
| 324 | project = Project.new(:name => 'Copy', :identifier => 'copy', :tracker_ids => [1]) |
||
| 325 | |||
| 326 | assert_difference 'Project.count' do |
||
| 327 | assert_difference 'Issue.count', 1+issue.descendants.count do |
||
| 328 | assert project.copy(source.reload) |
||
| 329 | end |
||
| 330 | end |
||
| 331 | copy = Issue.where(:parent_id => nil).order("id DESC").first
|
||
| 332 | assert_equal project, copy.project |
||
| 333 | assert_equal issue.descendants.count, copy.descendants.count |
||
| 334 | child_copy = copy.children.detect {|c| c.subject == 'Child1'}
|
||
| 335 | assert child_copy.descendants.any? |
||
| 336 | end |
||
| 337 | end |