To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 26 / 26f2b8dec33ec3e8eb2d5b55094ac09d33160993.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (19.5 KB)

1
require File.dirname(__FILE__) + '/test_helper'
2

    
3
class Note < ActiveRecord::Base
4
  acts_as_nested_set :scope => [:notable_id, :notable_type]
5
end
6

    
7
class AwesomeNestedSetTest < Test::Unit::TestCase
8

    
9
  class Default < ActiveRecord::Base
10
    acts_as_nested_set
11
    set_table_name 'categories'
12
  end
13
  class Scoped < ActiveRecord::Base
14
    acts_as_nested_set :scope => :organization
15
    set_table_name 'categories'
16
  end
17

    
18
  def test_left_column_default
19
    assert_equal 'lft', Default.acts_as_nested_set_options[:left_column]
20
  end
21

    
22
  def test_right_column_default
23
    assert_equal 'rgt', Default.acts_as_nested_set_options[:right_column]
24
  end
25

    
26
  def test_parent_column_default
27
    assert_equal 'parent_id', Default.acts_as_nested_set_options[:parent_column]
28
  end
29

    
30
  def test_scope_default
31
    assert_nil Default.acts_as_nested_set_options[:scope]
32
  end
33
  
34
  def test_left_column_name
35
    assert_equal 'lft', Default.left_column_name
36
    assert_equal 'lft', Default.new.left_column_name
37
  end
38

    
39
  def test_right_column_name
40
    assert_equal 'rgt', Default.right_column_name
41
    assert_equal 'rgt', Default.new.right_column_name
42
  end
43

    
44
  def test_parent_column_name
45
    assert_equal 'parent_id', Default.parent_column_name
46
    assert_equal 'parent_id', Default.new.parent_column_name
47
  end
48
  
49
  def test_quoted_left_column_name
50
    quoted = Default.connection.quote_column_name('lft')
51
    assert_equal quoted, Default.quoted_left_column_name
52
    assert_equal quoted, Default.new.quoted_left_column_name
53
  end
54

    
55
  def test_quoted_right_column_name
56
    quoted = Default.connection.quote_column_name('rgt')
57
    assert_equal quoted, Default.quoted_right_column_name
58
    assert_equal quoted, Default.new.quoted_right_column_name
59
  end
60

    
61
  def test_left_column_protected_from_assignment
62
    assert_raises(ActiveRecord::ActiveRecordError) { Category.new.lft = 1 }
63
  end
64
  
65
  def test_right_column_protected_from_assignment
66
    assert_raises(ActiveRecord::ActiveRecordError) { Category.new.rgt = 1 }
67
  end
68
  
69
  def test_parent_column_protected_from_assignment
70
    assert_raises(ActiveRecord::ActiveRecordError) { Category.new.parent_id = 1 }
71
  end
72
  
73
  def test_colums_protected_on_initialize
74
    c = Category.new(:lft => 1, :rgt => 2, :parent_id => 3)
75
    assert_nil c.lft
76
    assert_nil c.rgt
77
    assert_nil c.parent_id
78
  end
79
  
80
  def test_scoped_appends_id
81
    assert_equal :organization_id, Scoped.acts_as_nested_set_options[:scope]
82
  end
83
  
84
  def test_roots_class_method
85
    assert_equal Category.find_all_by_parent_id(nil), Category.roots
86
  end
87
    
88
  def test_root_class_method
89
    assert_equal categories(:top_level), Category.root
90
  end
91
  
92
  def test_root
93
    assert_equal categories(:top_level), categories(:child_3).root
94
  end
95
  
96
  def test_root?
97
    assert categories(:top_level).root?
98
    assert categories(:top_level_2).root?
99
  end
100
  
101
  def test_leaves_class_method
102
    assert_equal Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1"), Category.leaves
103
    assert_equal Category.leaves.count, 4
104
    assert (Category.leaves.include? categories(:child_1))
105
    assert (Category.leaves.include? categories(:child_2_1))
106
    assert (Category.leaves.include? categories(:child_3))
107
    assert (Category.leaves.include? categories(:top_level_2))
108
  end
109
  
110
  def test_leaf
111
    assert categories(:child_1).leaf?
112
    assert categories(:child_2_1).leaf?
113
    assert categories(:child_3).leaf?
114
    assert categories(:top_level_2).leaf?
115
    
116
    assert !categories(:top_level).leaf?
117
    assert !categories(:child_2).leaf?
118
  end
119
    
120
  def test_parent
121
    assert_equal categories(:child_2), categories(:child_2_1).parent
122
  end
123
  
124
  def test_self_and_ancestors
125
    child = categories(:child_2_1)
126
    self_and_ancestors = [categories(:top_level), categories(:child_2), child]
127
    assert_equal self_and_ancestors, child.self_and_ancestors
128
  end
129

    
130
  def test_ancestors
131
    child = categories(:child_2_1)
132
    ancestors = [categories(:top_level), categories(:child_2)]
133
    assert_equal ancestors, child.ancestors
134
  end
135
  
136
  def test_self_and_siblings
137
    child = categories(:child_2)
138
    self_and_siblings = [categories(:child_1), child, categories(:child_3)]
139
    assert_equal self_and_siblings, child.self_and_siblings
140
    assert_nothing_raised do
141
      tops = [categories(:top_level), categories(:top_level_2)]
142
      assert_equal tops, categories(:top_level).self_and_siblings
143
    end
144
  end
145

    
146
  def test_siblings
147
    child = categories(:child_2)
148
    siblings = [categories(:child_1), categories(:child_3)]
149
    assert_equal siblings, child.siblings
150
  end
151
  
152
  def test_leaves
153
    leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3), categories(:top_level_2)]
154
    assert categories(:top_level).leaves, leaves
155
  end
156
  
157
  def test_level
158
    assert_equal 0, categories(:top_level).level
159
    assert_equal 1, categories(:child_1).level
160
    assert_equal 2, categories(:child_2_1).level
161
  end
162
  
163
  def test_has_children?
164
    assert categories(:child_2_1).children.empty?
165
    assert !categories(:child_2).children.empty?
166
    assert !categories(:top_level).children.empty?
167
  end
168
  
169
  def test_self_and_descendents
170
    parent = categories(:top_level)
171
    self_and_descendants = [parent, categories(:child_1), categories(:child_2),
172
      categories(:child_2_1), categories(:child_3)]
173
    assert_equal self_and_descendants, parent.self_and_descendants
174
    assert_equal self_and_descendants, parent.self_and_descendants.count
175
  end
176
  
177
  def test_descendents
178
    lawyers = Category.create!(:name => "lawyers")
179
    us = Category.create!(:name => "United States")
180
    us.move_to_child_of(lawyers)
181
    patent = Category.create!(:name => "Patent Law")
182
    patent.move_to_child_of(us)
183
    lawyers.reload
184

    
185
    assert_equal 1, lawyers.children.size
186
    assert_equal 1, us.children.size
187
    assert_equal 2, lawyers.descendants.size
188
  end
189
  
190
  def test_self_and_descendents
191
    parent = categories(:top_level)
192
    descendants = [categories(:child_1), categories(:child_2),
193
      categories(:child_2_1), categories(:child_3)]
194
    assert_equal descendants, parent.descendants
195
  end
196
  
197
  def test_children
198
    category = categories(:top_level)
199
    category.children.each {|c| assert_equal category.id, c.parent_id }
200
  end
201
  
202
  def test_is_or_is_ancestor_of?
203
    assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_1))
204
    assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1))
205
    assert categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1))
206
    assert !categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2))
207
    assert !categories(:child_1).is_or_is_ancestor_of?(categories(:child_2))
208
    assert categories(:child_1).is_or_is_ancestor_of?(categories(:child_1))
209
  end
210
  
211
  def test_is_ancestor_of?
212
    assert categories(:top_level).is_ancestor_of?(categories(:child_1))
213
    assert categories(:top_level).is_ancestor_of?(categories(:child_2_1))
214
    assert categories(:child_2).is_ancestor_of?(categories(:child_2_1))
215
    assert !categories(:child_2_1).is_ancestor_of?(categories(:child_2))
216
    assert !categories(:child_1).is_ancestor_of?(categories(:child_2))
217
    assert !categories(:child_1).is_ancestor_of?(categories(:child_1))
218
  end
219

    
220
  def test_is_or_is_ancestor_of_with_scope
221
    root = Scoped.root
222
    child = root.children.first
223
    assert root.is_or_is_ancestor_of?(child)
224
    child.update_attribute :organization_id, 'different'
225
    assert !root.is_or_is_ancestor_of?(child)
226
  end
227

    
228
  def test_is_or_is_descendant_of?
229
    assert categories(:child_1).is_or_is_descendant_of?(categories(:top_level))
230
    assert categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level))
231
    assert categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2))
232
    assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1))
233
    assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_1))
234
    assert categories(:child_1).is_or_is_descendant_of?(categories(:child_1))
235
  end
236
  
237
  def test_is_descendant_of?
238
    assert categories(:child_1).is_descendant_of?(categories(:top_level))
239
    assert categories(:child_2_1).is_descendant_of?(categories(:top_level))
240
    assert categories(:child_2_1).is_descendant_of?(categories(:child_2))
241
    assert !categories(:child_2).is_descendant_of?(categories(:child_2_1))
242
    assert !categories(:child_2).is_descendant_of?(categories(:child_1))
243
    assert !categories(:child_1).is_descendant_of?(categories(:child_1))
244
  end
245
  
246
  def test_is_or_is_descendant_of_with_scope
247
    root = Scoped.root
248
    child = root.children.first
249
    assert child.is_or_is_descendant_of?(root)
250
    child.update_attribute :organization_id, 'different'
251
    assert !child.is_or_is_descendant_of?(root)
252
  end
253
  
254
  def test_same_scope?
255
    root = Scoped.root
256
    child = root.children.first
257
    assert child.same_scope?(root)
258
    child.update_attribute :organization_id, 'different'
259
    assert !child.same_scope?(root)
260
  end
261
  
262
  def test_left_sibling
263
    assert_equal categories(:child_1), categories(:child_2).left_sibling
264
    assert_equal categories(:child_2), categories(:child_3).left_sibling
265
  end
266

    
267
  def test_left_sibling_of_root
268
    assert_nil categories(:top_level).left_sibling
269
  end
270

    
271
  def test_left_sibling_without_siblings
272
    assert_nil categories(:child_2_1).left_sibling
273
  end
274

    
275
  def test_left_sibling_of_leftmost_node
276
    assert_nil categories(:child_1).left_sibling
277
  end
278

    
279
  def test_right_sibling
280
    assert_equal categories(:child_3), categories(:child_2).right_sibling
281
    assert_equal categories(:child_2), categories(:child_1).right_sibling
282
  end
283

    
284
  def test_right_sibling_of_root
285
    assert_equal categories(:top_level_2), categories(:top_level).right_sibling
286
    assert_nil categories(:top_level_2).right_sibling
287
  end
288

    
289
  def test_right_sibling_without_siblings
290
    assert_nil categories(:child_2_1).right_sibling
291
  end
292

    
293
  def test_right_sibling_of_rightmost_node
294
    assert_nil categories(:child_3).right_sibling
295
  end
296
  
297
  def test_move_left
298
    categories(:child_2).move_left
299
    assert_nil categories(:child_2).left_sibling
300
    assert_equal categories(:child_1), categories(:child_2).right_sibling
301
    assert Category.valid?
302
  end
303

    
304
  def test_move_right
305
    categories(:child_2).move_right
306
    assert_nil categories(:child_2).right_sibling
307
    assert_equal categories(:child_3), categories(:child_2).left_sibling
308
    assert Category.valid?
309
  end
310

    
311
  def test_move_to_left_of
312
    categories(:child_3).move_to_left_of(categories(:child_1))
313
    assert_nil categories(:child_3).left_sibling
314
    assert_equal categories(:child_1), categories(:child_3).right_sibling
315
    assert Category.valid?
316
  end
317

    
318
  def test_move_to_right_of
319
    categories(:child_1).move_to_right_of(categories(:child_3))
320
    assert_nil categories(:child_1).right_sibling
321
    assert_equal categories(:child_3), categories(:child_1).left_sibling
322
    assert Category.valid?
323
  end
324
  
325
  def test_move_to_root
326
    categories(:child_2).move_to_root
327
    assert_nil categories(:child_2).parent
328
    assert_equal 0, categories(:child_2).level
329
    assert_equal 1, categories(:child_2_1).level
330
    assert_equal 1, categories(:child_2).left
331
    assert_equal 4, categories(:child_2).right
332
    assert Category.valid?
333
  end
334

    
335
  def test_move_to_child_of
336
    categories(:child_1).move_to_child_of(categories(:child_3))
337
    assert_equal categories(:child_3).id, categories(:child_1).parent_id
338
    assert Category.valid?
339
  end
340
  
341
  def test_move_to_child_of_appends_to_end
342
    child = Category.create! :name => 'New Child'
343
    child.move_to_child_of categories(:top_level)
344
    assert_equal child, categories(:top_level).children.last
345
  end
346
  
347
  def test_subtree_move_to_child_of
348
    assert_equal 4, categories(:child_2).left
349
    assert_equal 7, categories(:child_2).right
350
    
351
    assert_equal 2, categories(:child_1).left
352
    assert_equal 3, categories(:child_1).right
353
    
354
    categories(:child_2).move_to_child_of(categories(:child_1))
355
    assert Category.valid?
356
    assert_equal categories(:child_1).id, categories(:child_2).parent_id
357
    
358
    assert_equal 3, categories(:child_2).left
359
    assert_equal 6, categories(:child_2).right
360
    assert_equal 2, categories(:child_1).left
361
    assert_equal 7, categories(:child_1).right    
362
  end
363
  
364
  def test_slightly_difficult_move_to_child_of
365
    assert_equal 11, categories(:top_level_2).left
366
    assert_equal 12, categories(:top_level_2).right
367
    
368
    # create a new top-level node and move single-node top-level tree inside it.
369
    new_top = Category.create(:name => 'New Top')
370
    assert_equal 13, new_top.left
371
    assert_equal 14, new_top.right
372
    
373
    categories(:top_level_2).move_to_child_of(new_top)
374
    
375
    assert Category.valid?
376
    assert_equal new_top.id, categories(:top_level_2).parent_id
377
    
378
    assert_equal 12, categories(:top_level_2).left
379
    assert_equal 13, categories(:top_level_2).right
380
    assert_equal 11, new_top.left
381
    assert_equal 14, new_top.right    
382
  end
383
  
384
  def test_difficult_move_to_child_of
385
    assert_equal 1, categories(:top_level).left
386
    assert_equal 10, categories(:top_level).right
387
    assert_equal 5, categories(:child_2_1).left
388
    assert_equal 6, categories(:child_2_1).right
389
    
390
    # create a new top-level node and move an entire top-level tree inside it.
391
    new_top = Category.create(:name => 'New Top')
392
    categories(:top_level).move_to_child_of(new_top)
393
    categories(:child_2_1).reload
394
    assert Category.valid?  
395
    assert_equal new_top.id, categories(:top_level).parent_id
396
    
397
    assert_equal 4, categories(:top_level).left
398
    assert_equal 13, categories(:top_level).right
399
    assert_equal 8, categories(:child_2_1).left
400
    assert_equal 9, categories(:child_2_1).right    
401
  end
402

    
403
  #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
404
  def test_move_to_child_more_than_once_per_parent_rebuild
405
    root1 = Category.create(:name => 'Root1')
406
    root2 = Category.create(:name => 'Root2')
407
    root3 = Category.create(:name => 'Root3')
408
    
409
    root2.move_to_child_of root1
410
    root3.move_to_child_of root1
411
      
412
    output = Category.roots.last.to_text
413
    Category.update_all('lft = null, rgt = null')
414
    Category.rebuild!
415
    
416
    assert_equal Category.roots.last.to_text, output
417
  end
418
  
419
  # doing move_to_child twice onto same parent from the furthest right first
420
  def test_move_to_child_more_than_once_per_parent_outside_in
421
    node1 = Category.create(:name => 'Node-1')
422
    node2 = Category.create(:name => 'Node-2')
423
    node3 = Category.create(:name => 'Node-3')
424
    
425
    node2.move_to_child_of node1
426
    node3.move_to_child_of node1
427
      
428
    output = Category.roots.last.to_text
429
    Category.update_all('lft = null, rgt = null')
430
    Category.rebuild!
431
    
432
    assert_equal Category.roots.last.to_text, output
433
  end
434

    
435

    
436
  def test_valid_with_null_lefts
437
    assert Category.valid?
438
    Category.update_all('lft = null')
439
    assert !Category.valid?
440
  end
441

    
442
  def test_valid_with_null_rights
443
    assert Category.valid?
444
    Category.update_all('rgt = null')
445
    assert !Category.valid?
446
  end
447
  
448
  def test_valid_with_missing_intermediate_node
449
    # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
450
    assert Category.valid?
451
    Category.delete(categories(:child_2).id)
452
    assert Category.valid?
453
  end
454
  
455
  def test_valid_with_overlapping_and_rights
456
    assert Category.valid?
457
    categories(:top_level_2)['lft'] = 0
458
    categories(:top_level_2).save
459
    assert !Category.valid?
460
  end
461
  
462
  def test_rebuild
463
    assert Category.valid?
464
    before_text = Category.root.to_text
465
    Category.update_all('lft = null, rgt = null')
466
    Category.rebuild!
467
    assert Category.valid?
468
    assert_equal before_text, Category.root.to_text
469
  end
470
  
471
  def test_move_possible_for_sibling
472
    assert categories(:child_2).move_possible?(categories(:child_1))
473
  end
474
  
475
  def test_move_not_possible_to_self
476
    assert !categories(:top_level).move_possible?(categories(:top_level))
477
  end
478
  
479
  def test_move_not_possible_to_parent
480
    categories(:top_level).descendants.each do |descendant|
481
      assert !categories(:top_level).move_possible?(descendant)
482
      assert descendant.move_possible?(categories(:top_level))
483
    end
484
  end
485
  
486
  def test_is_or_is_ancestor_of?
487
    [:child_1, :child_2, :child_2_1, :child_3].each do |c|
488
      assert categories(:top_level).is_or_is_ancestor_of?(categories(c))
489
    end
490
    assert !categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2))
491
  end
492
  
493
  def test_left_and_rights_valid_with_blank_left
494
    assert Category.left_and_rights_valid?
495
    categories(:child_2)[:lft] = nil
496
    categories(:child_2).save(false)
497
    assert !Category.left_and_rights_valid?
498
  end
499

    
500
  def test_left_and_rights_valid_with_blank_right
501
    assert Category.left_and_rights_valid?
502
    categories(:child_2)[:rgt] = nil
503
    categories(:child_2).save(false)
504
    assert !Category.left_and_rights_valid?
505
  end
506

    
507
  def test_left_and_rights_valid_with_equal
508
    assert Category.left_and_rights_valid?
509
    categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
510
    categories(:top_level_2).save(false)
511
    assert !Category.left_and_rights_valid?
512
  end
513

    
514
  def test_left_and_rights_valid_with_left_equal_to_parent
515
    assert Category.left_and_rights_valid?
516
    categories(:child_2)[:lft] = categories(:top_level)[:lft]
517
    categories(:child_2).save(false)
518
    assert !Category.left_and_rights_valid?
519
  end
520

    
521
  def test_left_and_rights_valid_with_right_equal_to_parent
522
    assert Category.left_and_rights_valid?
523
    categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
524
    categories(:child_2).save(false)
525
    assert !Category.left_and_rights_valid?
526
  end
527
  
528
  def test_moving_dirty_objects_doesnt_invalidate_tree
529
    r1 = Category.create
530
    r2 = Category.create
531
    r3 = Category.create
532
    r4 = Category.create
533
    nodes = [r1, r2, r3, r4]
534
    
535
    r2.move_to_child_of(r1)
536
    assert Category.valid?
537
    
538
    r3.move_to_child_of(r1)
539
    assert Category.valid?
540
    
541
    r4.move_to_child_of(r2)
542
    assert Category.valid?
543
  end
544
  
545
  def test_multi_scoped_no_duplicates_for_columns?
546
    assert_nothing_raised do
547
      Note.no_duplicates_for_columns?
548
    end
549
  end
550

    
551
  def test_multi_scoped_all_roots_valid?
552
    assert_nothing_raised do
553
      Note.all_roots_valid?
554
    end
555
  end
556

    
557
  def test_multi_scoped
558
    note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
559
    note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
560
    note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
561
    
562
    assert_equal [note1, note2], note1.self_and_siblings
563
    assert_equal [note3], note3.self_and_siblings
564
  end
565
  
566
  def test_multi_scoped_rebuild
567
    root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
568
    child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
569
    child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
570
    
571
    child1.move_to_child_of root
572
    child2.move_to_child_of root
573
          
574
    Note.update_all('lft = null, rgt = null')
575
    Note.rebuild!
576
    
577
    assert_equal Note.roots.find_by_body('A'), root
578
    assert_equal [child1, child2], Note.roots.find_by_body('A').children
579
  end
580
  
581
  def test_same_scope_with_multi_scopes
582
    assert_nothing_raised do
583
      notes(:scope1).same_scope?(notes(:child_1))
584
    end
585
    assert notes(:scope1).same_scope?(notes(:child_1))
586
    assert notes(:child_1).same_scope?(notes(:scope1))
587
    assert !notes(:scope1).same_scope?(notes(:scope2))
588
  end
589
  
590
  def test_quoting_of_multi_scope_column_names
591
    assert_equal ["\"notable_id\"", "\"notable_type\""], Note.quoted_scope_column_names
592
  end
593
  
594
  def test_equal_in_same_scope
595
    assert_equal notes(:scope1), notes(:scope1)
596
    assert_not_equal notes(:scope1), notes(:child_1)
597
  end
598
  
599
  def test_equal_in_different_scopes
600
    assert_not_equal notes(:scope1), notes(:scope2)
601
  end
602
  
603
end