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