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