##// END OF EJS Templates
Added shoulda macros to test Project's associations...
Eric Davis -
r2822:61c09b644269
parent child
Show More
@@ -1,421 +1,445
1 1 # redMine - project management software
2 2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require File.dirname(__FILE__) + '/../test_helper'
19 19
20 20 class ProjectTest < ActiveSupport::TestCase
21 21 fixtures :projects, :enabled_modules,
22 22 :issues, :issue_statuses, :journals, :journal_details,
23 23 :users, :members, :member_roles, :roles, :projects_trackers, :trackers, :boards,
24 24 :queries
25 25
26 26 def setup
27 27 @ecookbook = Project.find(1)
28 28 @ecookbook_sub1 = Project.find(3)
29 29 end
30 30
31 31 should_validate_presence_of :name
32 32 should_validate_presence_of :identifier
33 33
34 34 should_validate_uniqueness_of :name
35 35 should_validate_uniqueness_of :identifier
36 36
37 context "associations" do
38 should_have_many :members
39 should_have_many :users, :through => :members
40 should_have_many :member_principals
41 should_have_many :principals, :through => :member_principals
42 should_have_many :enabled_modules
43 should_have_many :issues
44 should_have_many :issue_changes, :through => :issues
45 should_have_many :versions
46 should_have_many :time_entries
47 should_have_many :queries
48 should_have_many :documents
49 should_have_many :news
50 should_have_many :issue_categories
51 should_have_many :boards
52 should_have_many :changesets, :through => :repository
53
54 should_have_one :repository
55 should_have_one :wiki
56
57 should_have_and_belong_to_many :trackers
58 should_have_and_belong_to_many :issue_custom_fields
59 end
60
37 61 def test_truth
38 62 assert_kind_of Project, @ecookbook
39 63 assert_equal "eCookbook", @ecookbook.name
40 64 end
41 65
42 66 def test_update
43 67 assert_equal "eCookbook", @ecookbook.name
44 68 @ecookbook.name = "eCook"
45 69 assert @ecookbook.save, @ecookbook.errors.full_messages.join("; ")
46 70 @ecookbook.reload
47 71 assert_equal "eCook", @ecookbook.name
48 72 end
49 73
50 74 def test_validate_identifier
51 75 to_test = {"abc" => true,
52 76 "ab12" => true,
53 77 "ab-12" => true,
54 78 "12" => false,
55 79 "new" => false}
56 80
57 81 to_test.each do |identifier, valid|
58 82 p = Project.new
59 83 p.identifier = identifier
60 84 p.valid?
61 85 assert_equal valid, p.errors.on('identifier').nil?
62 86 end
63 87 end
64 88
65 89 def test_members_should_be_active_users
66 90 Project.all.each do |project|
67 91 assert_nil project.members.detect {|m| !(m.user.is_a?(User) && m.user.active?) }
68 92 end
69 93 end
70 94
71 95 def test_users_should_be_active_users
72 96 Project.all.each do |project|
73 97 assert_nil project.users.detect {|u| !(u.is_a?(User) && u.active?) }
74 98 end
75 99 end
76 100
77 101 def test_archive
78 102 user = @ecookbook.members.first.user
79 103 @ecookbook.archive
80 104 @ecookbook.reload
81 105
82 106 assert !@ecookbook.active?
83 107 assert !user.projects.include?(@ecookbook)
84 108 # Subproject are also archived
85 109 assert !@ecookbook.children.empty?
86 110 assert @ecookbook.descendants.active.empty?
87 111 end
88 112
89 113 def test_unarchive
90 114 user = @ecookbook.members.first.user
91 115 @ecookbook.archive
92 116 # A subproject of an archived project can not be unarchived
93 117 assert !@ecookbook_sub1.unarchive
94 118
95 119 # Unarchive project
96 120 assert @ecookbook.unarchive
97 121 @ecookbook.reload
98 122 assert @ecookbook.active?
99 123 assert user.projects.include?(@ecookbook)
100 124 # Subproject can now be unarchived
101 125 @ecookbook_sub1.reload
102 126 assert @ecookbook_sub1.unarchive
103 127 end
104 128
105 129 def test_destroy
106 130 # 2 active members
107 131 assert_equal 2, @ecookbook.members.size
108 132 # and 1 is locked
109 133 assert_equal 3, Member.find(:all, :conditions => ['project_id = ?', @ecookbook.id]).size
110 134 # some boards
111 135 assert @ecookbook.boards.any?
112 136
113 137 @ecookbook.destroy
114 138 # make sure that the project non longer exists
115 139 assert_raise(ActiveRecord::RecordNotFound) { Project.find(@ecookbook.id) }
116 140 # make sure related data was removed
117 141 assert Member.find(:all, :conditions => ['project_id = ?', @ecookbook.id]).empty?
118 142 assert Board.find(:all, :conditions => ['project_id = ?', @ecookbook.id]).empty?
119 143 end
120 144
121 145 def test_move_an_orphan_project_to_a_root_project
122 146 sub = Project.find(2)
123 147 sub.set_parent! @ecookbook
124 148 assert_equal @ecookbook.id, sub.parent.id
125 149 @ecookbook.reload
126 150 assert_equal 4, @ecookbook.children.size
127 151 end
128 152
129 153 def test_move_an_orphan_project_to_a_subproject
130 154 sub = Project.find(2)
131 155 assert sub.set_parent!(@ecookbook_sub1)
132 156 end
133 157
134 158 def test_move_a_root_project_to_a_project
135 159 sub = @ecookbook
136 160 assert sub.set_parent!(Project.find(2))
137 161 end
138 162
139 163 def test_should_not_move_a_project_to_its_children
140 164 sub = @ecookbook
141 165 assert !(sub.set_parent!(Project.find(3)))
142 166 end
143 167
144 168 def test_set_parent_should_add_roots_in_alphabetical_order
145 169 ProjectCustomField.delete_all
146 170 Project.delete_all
147 171 Project.create!(:name => 'Project C', :identifier => 'project-c').set_parent!(nil)
148 172 Project.create!(:name => 'Project B', :identifier => 'project-b').set_parent!(nil)
149 173 Project.create!(:name => 'Project D', :identifier => 'project-d').set_parent!(nil)
150 174 Project.create!(:name => 'Project A', :identifier => 'project-a').set_parent!(nil)
151 175
152 176 assert_equal 4, Project.count
153 177 assert_equal Project.all.sort_by(&:name), Project.all.sort_by(&:lft)
154 178 end
155 179
156 180 def test_set_parent_should_add_children_in_alphabetical_order
157 181 ProjectCustomField.delete_all
158 182 parent = Project.create!(:name => 'Parent', :identifier => 'parent')
159 183 Project.create!(:name => 'Project C', :identifier => 'project-c').set_parent!(parent)
160 184 Project.create!(:name => 'Project B', :identifier => 'project-b').set_parent!(parent)
161 185 Project.create!(:name => 'Project D', :identifier => 'project-d').set_parent!(parent)
162 186 Project.create!(:name => 'Project A', :identifier => 'project-a').set_parent!(parent)
163 187
164 188 parent.reload
165 189 assert_equal 4, parent.children.size
166 190 assert_equal parent.children.sort_by(&:name), parent.children
167 191 end
168 192
169 193 def test_rebuild_should_sort_children_alphabetically
170 194 ProjectCustomField.delete_all
171 195 parent = Project.create!(:name => 'Parent', :identifier => 'parent')
172 196 Project.create!(:name => 'Project C', :identifier => 'project-c').move_to_child_of(parent)
173 197 Project.create!(:name => 'Project B', :identifier => 'project-b').move_to_child_of(parent)
174 198 Project.create!(:name => 'Project D', :identifier => 'project-d').move_to_child_of(parent)
175 199 Project.create!(:name => 'Project A', :identifier => 'project-a').move_to_child_of(parent)
176 200
177 201 Project.update_all("lft = NULL, rgt = NULL")
178 202 Project.rebuild!
179 203
180 204 parent.reload
181 205 assert_equal 4, parent.children.size
182 206 assert_equal parent.children.sort_by(&:name), parent.children
183 207 end
184 208
185 209 def test_parent
186 210 p = Project.find(6).parent
187 211 assert p.is_a?(Project)
188 212 assert_equal 5, p.id
189 213 end
190 214
191 215 def test_ancestors
192 216 a = Project.find(6).ancestors
193 217 assert a.first.is_a?(Project)
194 218 assert_equal [1, 5], a.collect(&:id)
195 219 end
196 220
197 221 def test_root
198 222 r = Project.find(6).root
199 223 assert r.is_a?(Project)
200 224 assert_equal 1, r.id
201 225 end
202 226
203 227 def test_children
204 228 c = Project.find(1).children
205 229 assert c.first.is_a?(Project)
206 230 assert_equal [5, 3, 4], c.collect(&:id)
207 231 end
208 232
209 233 def test_descendants
210 234 d = Project.find(1).descendants
211 235 assert d.first.is_a?(Project)
212 236 assert_equal [5, 6, 3, 4], d.collect(&:id)
213 237 end
214 238
215 239 def test_users_by_role
216 240 users_by_role = Project.find(1).users_by_role
217 241 assert_kind_of Hash, users_by_role
218 242 role = Role.find(1)
219 243 assert_kind_of Array, users_by_role[role]
220 244 assert users_by_role[role].include?(User.find(2))
221 245 end
222 246
223 247 def test_rolled_up_trackers
224 248 parent = Project.find(1)
225 249 parent.trackers = Tracker.find([1,2])
226 250 child = parent.children.find(3)
227 251
228 252 assert_equal [1, 2], parent.tracker_ids
229 253 assert_equal [2, 3], child.trackers.collect(&:id)
230 254
231 255 assert_kind_of Tracker, parent.rolled_up_trackers.first
232 256 assert_equal Tracker.find(1), parent.rolled_up_trackers.first
233 257
234 258 assert_equal [1, 2, 3], parent.rolled_up_trackers.collect(&:id)
235 259 assert_equal [2, 3], child.rolled_up_trackers.collect(&:id)
236 260 end
237 261
238 262 def test_rolled_up_trackers_should_ignore_archived_subprojects
239 263 parent = Project.find(1)
240 264 parent.trackers = Tracker.find([1,2])
241 265 child = parent.children.find(3)
242 266 child.trackers = Tracker.find([1,3])
243 267 parent.children.each(&:archive)
244 268
245 269 assert_equal [1,2], parent.rolled_up_trackers.collect(&:id)
246 270 end
247 271
248 272 def test_next_identifier
249 273 ProjectCustomField.delete_all
250 274 Project.create!(:name => 'last', :identifier => 'p2008040')
251 275 assert_equal 'p2008041', Project.next_identifier
252 276 end
253 277
254 278 def test_next_identifier_first_project
255 279 Project.delete_all
256 280 assert_nil Project.next_identifier
257 281 end
258 282
259 283
260 284 def test_enabled_module_names_should_not_recreate_enabled_modules
261 285 project = Project.find(1)
262 286 # Remove one module
263 287 modules = project.enabled_modules.slice(0..-2)
264 288 assert modules.any?
265 289 assert_difference 'EnabledModule.count', -1 do
266 290 project.enabled_module_names = modules.collect(&:name)
267 291 end
268 292 project.reload
269 293 # Ids should be preserved
270 294 assert_equal project.enabled_module_ids.sort, modules.collect(&:id).sort
271 295 end
272 296
273 297 def test_copy_from_existing_project
274 298 source_project = Project.find(1)
275 299 copied_project = Project.copy_from(1)
276 300
277 301 assert copied_project
278 302 # Cleared attributes
279 303 assert copied_project.id.blank?
280 304 assert copied_project.name.blank?
281 305 assert copied_project.identifier.blank?
282 306
283 307 # Duplicated attributes
284 308 assert_equal source_project.description, copied_project.description
285 309 assert_equal source_project.enabled_modules, copied_project.enabled_modules
286 310 assert_equal source_project.trackers, copied_project.trackers
287 311
288 312 # Default attributes
289 313 assert_equal 1, copied_project.status
290 314 end
291 315
292 316 context "Project#copy" do
293 317 setup do
294 318 ProjectCustomField.destroy_all # Custom values are a mess to isolate in tests
295 319 Project.destroy_all :identifier => "copy-test"
296 320 @source_project = Project.find(2)
297 321 @project = Project.new(:name => 'Copy Test', :identifier => 'copy-test')
298 322 @project.trackers = @source_project.trackers
299 323 @project.enabled_modules = @source_project.enabled_modules
300 324 end
301 325
302 326 should "copy issues" do
303 327 assert @project.valid?
304 328 assert @project.issues.empty?
305 329 assert @project.copy(@source_project)
306 330
307 331 assert_equal @source_project.issues.size, @project.issues.size
308 332 @project.issues.each do |issue|
309 333 assert issue.valid?
310 334 assert ! issue.assigned_to.blank?
311 335 assert_equal @project, issue.project
312 336 end
313 337 end
314 338
315 339 should "change the new issues to use the copied version" do
316 340 assigned_version = Version.generate!(:name => "Assigned Issues")
317 341 @source_project.versions << assigned_version
318 342 assert_equal 1, @source_project.versions.size
319 343 @source_project.issues << Issue.generate!(:fixed_version_id => assigned_version.id,
320 344 :subject => "change the new issues to use the copied version",
321 345 :tracker_id => 1,
322 346 :project_id => @source_project.id)
323 347
324 348 assert @project.copy(@source_project)
325 349 @project.reload
326 350 copied_issue = @project.issues.first(:conditions => {:subject => "change the new issues to use the copied version"})
327 351
328 352 assert copied_issue
329 353 assert copied_issue.fixed_version
330 354 assert_equal "Assigned Issues", copied_issue.fixed_version.name # Same name
331 355 assert_not_equal assigned_version.id, copied_issue.fixed_version.id # Different record
332 356 end
333 357
334 358 should "copy members" do
335 359 assert @project.valid?
336 360 assert @project.members.empty?
337 361 assert @project.copy(@source_project)
338 362
339 363 assert_equal @source_project.members.size, @project.members.size
340 364 @project.members.each do |member|
341 365 assert member
342 366 assert_equal @project, member.project
343 367 end
344 368 end
345 369
346 370 should "copy project specific queries" do
347 371 assert @project.valid?
348 372 assert @project.queries.empty?
349 373 assert @project.copy(@source_project)
350 374
351 375 assert_equal @source_project.queries.size, @project.queries.size
352 376 @project.queries.each do |query|
353 377 assert query
354 378 assert_equal @project, query.project
355 379 end
356 380 end
357 381
358 382 should "copy versions" do
359 383 @source_project.versions << Version.generate!
360 384 @source_project.versions << Version.generate!
361 385
362 386 assert @project.versions.empty?
363 387 assert @project.copy(@source_project)
364 388
365 389 assert_equal @source_project.versions.size, @project.versions.size
366 390 @project.versions.each do |version|
367 391 assert version
368 392 assert_equal @project, version.project
369 393 end
370 394 end
371 395
372 396 should "copy wiki" do
373 397 assert @project.copy(@source_project)
374 398
375 399 assert @project.wiki
376 400 assert_not_equal @source_project.wiki, @project.wiki
377 401 assert_equal "Start page", @project.wiki.start_page
378 402 end
379 403
380 404 should "copy wiki pages and content" do
381 405 assert @project.copy(@source_project)
382 406
383 407 assert @project.wiki
384 408 assert_equal 1, @project.wiki.pages.length
385 409
386 410 @project.wiki.pages.each do |wiki_page|
387 411 assert wiki_page.content
388 412 assert !@source_project.wiki.pages.include?(wiki_page)
389 413 end
390 414 end
391 415
392 416 should "copy custom fields"
393 417
394 418 should "copy issue categories" do
395 419 assert @project.copy(@source_project)
396 420
397 421 assert_equal 2, @project.issue_categories.size
398 422 @project.issue_categories.each do |issue_category|
399 423 assert !@source_project.issue_categories.include?(issue_category)
400 424 end
401 425 end
402 426
403 427 should "change the new issues to use the copied issue categories" do
404 428 issue = Issue.find(4)
405 429 issue.update_attribute(:category_id, 3)
406 430
407 431 assert @project.copy(@source_project)
408 432
409 433 @project.issues.each do |issue|
410 434 assert issue.category
411 435 assert_equal "Stock management", issue.category.name # Same name
412 436 assert_not_equal IssueCategory.find(3), issue.category # Different record
413 437 end
414 438 end
415 439
416 440 should "copy issue relations"
417 441 should "link issue relations if cross project issue relations are valid"
418 442
419 443 end
420 444
421 445 end
General Comments 0
You need to be logged in to leave comments. Login now