mongo_nested_set 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/rails/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "mongo_nested_set"
2
+
3
+ MongoMapper::Document.append_inclusions MongoNestedSet
@@ -0,0 +1,19 @@
1
+ class Category
2
+ include MongoMapper::Document
3
+
4
+ acts_as_nested_set
5
+
6
+ key :organization_id, String
7
+
8
+ def to_s
9
+ name
10
+ end
11
+
12
+ def recurse &block
13
+ block.call self, lambda{
14
+ self.children.each do |child|
15
+ child.recurse &block
16
+ end
17
+ }
18
+ end
19
+ end
@@ -0,0 +1,795 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class CategoryFixture
4
+ include MongoMapper::Document
5
+ set_collection_name 'categories'
6
+ end
7
+ class DepartmentFixture
8
+ include MongoMapper::Document
9
+ set_collection_name 'departments'
10
+ end
11
+ class NoteFixture
12
+ include MongoMapper::Document
13
+ set_collection_name 'notes'
14
+ end
15
+
16
+ class Note
17
+ include MongoMapper::Document
18
+ acts_as_nested_set :scope => [:notable_id, :notable_type]
19
+ end
20
+ class Default
21
+ include MongoMapper::Document
22
+ acts_as_nested_set
23
+ set_collection_name 'categories'
24
+ end
25
+ class ScopedCategory
26
+ include MongoMapper::Document
27
+ key :organization_id, String
28
+
29
+ acts_as_nested_set :scope => :organization
30
+ set_collection_name 'categories'
31
+ end
32
+ class RenamedColumns
33
+ include MongoMapper::Document
34
+ acts_as_nested_set :parent_column => 'mother_id', :left_column => 'red', :right_column => 'black'
35
+ end
36
+ class Department
37
+ include MongoMapper::Document
38
+ acts_as_nested_set
39
+ end
40
+
41
+ class AwesomeNestedSetTest < TestCaseClass
42
+ def setup
43
+ MongoMapper.database.collections.each(&:drop)
44
+ MongoMapper.database.create_collection "categories"
45
+
46
+ create_category :top_level, { :name => "Top Level", :lft => 1, :rgt => 10 }
47
+ create_category :child_1, { :name => "Child 1", :parent_id => categories(:top_level).id, :lft => 2, :rgt => 3 }
48
+ create_category :child_2, { :name => "Child 2", :parent_id => categories(:top_level).id, :lft => 4, :rgt => 7 }
49
+ create_category :child_2_1, { :name => "Child 2.1", :parent_id => categories(:child_2).id, :lft => 5, :rgt => 6 }
50
+ create_category :child_3, { :name => "Child 3", :parent_id => categories(:top_level).id, :lft => 8, :rgt => 9 }
51
+ create_category :top_level_2, { :name => "Top Level 2", :lft => 11, :rgt => 12 }
52
+ create_department :top, { :name => "Top" }
53
+ create_note :scope1, { :body => "Top Level", :lft => 1, :rgt => 10, :notable_id => categories(:top_level).id, :notable_type => "Category" }
54
+ create_note :scope1, { :body => "Top Level", :lft => 1, :rgt => 10, :notable_id => categories(:top_level).id, :notable_type => "Category" }
55
+ create_note :child_1, { :body => "Child 1", :parent_id => notes(:scope1).id, :lft => 2, :rgt => 3, :notable_id => categories(:top_level).id, :notable_type => "Category" }
56
+ create_note :child_2, { :body => "Child 2", :parent_id => notes(:scope1).id, :lft => 4, :rgt => 7, :notable_id => categories(:top_level).id, :notable_type => "Category" }
57
+ create_note :child_3, { :body => "Child 3", :parent_id => notes(:scope1).id, :lft => 8, :rgt => 9, :notable_id => categories(:top_level).id, :notable_type => "Category" }
58
+ create_note :scope2, { :body => "Top Level 2", :lft => 1, :rgt => 2, :notable_id => departments(:top).id, :notable_type => "Departments" }
59
+ end
60
+
61
+ def create_fixture(type, key, options = {})
62
+ @fixtures ||= {}
63
+ @fixtures[type] ||= {}
64
+ dummy = "#{type}_fixture".classify.constantize.create(options)
65
+ @fixtures[type][key] = type.to_s.classify.constantize.find dummy.id
66
+ end
67
+
68
+ def create_category(key, options = {})
69
+ create_fixture :category, key, options
70
+ end
71
+
72
+ def categories(key)
73
+ @fixtures[:category][key]
74
+ end
75
+
76
+ def create_department(key, options = {})
77
+ create_fixture :department, key, options
78
+ end
79
+
80
+ def departments(key)
81
+ @fixtures[:department][key]
82
+ end
83
+
84
+ def create_note(key, options = {})
85
+ create_fixture :note, key, options
86
+ end
87
+
88
+ def notes(key)
89
+ @fixtures[:note][key]
90
+ end
91
+
92
+ def test_left_column_default
93
+ assert_equal 'lft', Default.acts_as_nested_set_options[:left_column]
94
+ end
95
+
96
+ def test_right_column_default
97
+ assert_equal 'rgt', Default.acts_as_nested_set_options[:right_column]
98
+ end
99
+
100
+ def test_parent_column_default
101
+ assert_equal 'parent_id', Default.acts_as_nested_set_options[:parent_column]
102
+ end
103
+
104
+ def test_scope_default
105
+ assert_nil Default.acts_as_nested_set_options[:scope]
106
+ end
107
+
108
+ def test_left_column_name
109
+ assert_equal 'lft', Default.left_column_name
110
+ assert_equal 'lft', Default.new.left_column_name
111
+ assert_equal 'red', RenamedColumns.left_column_name
112
+ assert_equal 'red', RenamedColumns.new.left_column_name
113
+ end
114
+
115
+ def test_right_column_name
116
+ assert_equal 'rgt', Default.right_column_name
117
+ assert_equal 'rgt', Default.new.right_column_name
118
+ assert_equal 'black', RenamedColumns.right_column_name
119
+ assert_equal 'black', RenamedColumns.new.right_column_name
120
+ end
121
+
122
+ def test_parent_column_name
123
+ assert_equal 'parent_id', Default.parent_column_name
124
+ assert_equal 'parent_id', Default.new.parent_column_name
125
+ assert_equal 'mother_id', RenamedColumns.parent_column_name
126
+ assert_equal 'mother_id', RenamedColumns.new.parent_column_name
127
+ end
128
+
129
+ def test_creation_with_altered_column_names
130
+ assert_nothing_raised do
131
+ RenamedColumns.create!()
132
+ end
133
+ end
134
+
135
+ def test_scoped_appends_id
136
+ assert_equal :organization_id, ScopedCategory.acts_as_nested_set_options[:scope]
137
+ end
138
+
139
+ def test_roots_class_method
140
+ assert_equal Category.find_all_by_parent_id(nil), Category.roots
141
+ end
142
+
143
+ def test_root_class_method
144
+ assert_equal categories(:top_level), Category.root
145
+ end
146
+
147
+ def test_root
148
+ assert_equal categories(:top_level), categories(:child_3).root
149
+ end
150
+
151
+ def test_root?
152
+ assert categories(:top_level).root?
153
+ assert categories(:top_level_2).root?
154
+ end
155
+
156
+ # def test_leaves_class_method
157
+ # assert_equal Category.find(:all, :conditions => "#{Category.right_column_name} - #{Category.left_column_name} = 1"), Category.leaves
158
+ # assert_equal Category.leaves.count, 4
159
+ # assert (Category.leaves.include? categories(:child_1))
160
+ # assert (Category.leaves.include? categories(:child_2_1))
161
+ # assert (Category.leaves.include? categories(:child_3))
162
+ # assert (Category.leaves.include? categories(:top_level_2))
163
+ # end
164
+
165
+ def test_leaf
166
+ assert categories(:child_1).leaf?
167
+ assert categories(:child_2_1).leaf?
168
+ assert categories(:child_3).leaf?
169
+ assert categories(:top_level_2).leaf?
170
+
171
+ assert !categories(:top_level).leaf?
172
+ assert !categories(:child_2).leaf?
173
+ assert !Category.new.leaf?
174
+ end
175
+
176
+ def test_parent
177
+ assert_equal categories(:child_2), categories(:child_2_1).parent
178
+ end
179
+
180
+ def test_self_and_ancestors
181
+ child = categories(:child_2_1)
182
+ self_and_ancestors = [categories(:top_level), categories(:child_2), child]
183
+ assert_equal self_and_ancestors, child.self_and_ancestors
184
+ end
185
+
186
+ def test_ancestors
187
+ child = categories(:child_2_1)
188
+ ancestors = [categories(:top_level), categories(:child_2)]
189
+ assert_equal ancestors, child.ancestors
190
+ end
191
+
192
+ def test_self_and_siblings
193
+ child = categories(:child_2)
194
+ self_and_siblings = [categories(:child_1), child, categories(:child_3)]
195
+ assert_equal self_and_siblings, child.self_and_siblings
196
+ assert_nothing_raised do
197
+ tops = [categories(:top_level), categories(:top_level_2)]
198
+ assert_equal tops, categories(:top_level).self_and_siblings
199
+ end
200
+ end
201
+
202
+ def test_siblings
203
+ child = categories(:child_2)
204
+ siblings = [categories(:child_1), categories(:child_3)]
205
+ assert_equal siblings, child.siblings
206
+ end
207
+
208
+ #
209
+ # def test_leaves
210
+ # leaves = [categories(:child_1), categories(:child_2_1), categories(:child_3), categories(:top_level_2)]
211
+ # assert categories(:top_level).leaves, leaves
212
+ # end
213
+ #
214
+ def test_level
215
+ assert_equal 0, categories(:top_level).level
216
+ assert_equal 1, categories(:child_1).level
217
+ assert_equal 2, categories(:child_2_1).level
218
+ end
219
+
220
+ def test_has_children?
221
+ assert categories(:child_2_1).children.empty?
222
+ assert !categories(:child_2).children.empty?
223
+ assert !categories(:top_level).children.empty?
224
+ end
225
+
226
+ def test_self_and_descendents
227
+ parent = categories(:top_level)
228
+ self_and_descendants = [parent, categories(:child_1), categories(:child_2),
229
+ categories(:child_2_1), categories(:child_3)]
230
+ assert_equal self_and_descendants, parent.self_and_descendants
231
+ assert_equal self_and_descendants, parent.self_and_descendants.count
232
+ end
233
+
234
+ def test_descendents
235
+ lawyers = Category.create!(:name => "lawyers")
236
+ us = Category.create!(:name => "United States")
237
+ us.move_to_child_of(lawyers)
238
+ assert_not_nil us.lft
239
+ assert_not_nil us.rgt
240
+ patent = Category.create!(:name => "Patent Law")
241
+ patent.move_to_child_of(us)
242
+ lawyers.reload
243
+
244
+ assert_equal 1, lawyers.children.size
245
+ assert_equal 1, us.children.size
246
+ assert_equal 2, lawyers.descendants.size
247
+ end
248
+
249
+ def test_self_and_descendents
250
+ parent = categories(:top_level)
251
+ descendants = [categories(:child_1), categories(:child_2),
252
+ categories(:child_2_1), categories(:child_3)]
253
+ assert_equal descendants, parent.descendants
254
+ end
255
+
256
+ def test_children
257
+ category = categories(:top_level)
258
+ category.children.each {|c| assert_equal category.id, c.parent_id }
259
+ end
260
+
261
+ def test_order_of_children
262
+ categories(:child_2).move_left
263
+ assert_equal categories(:child_2), categories(:top_level).children[0]
264
+ assert_equal categories(:child_1), categories(:top_level).children[1]
265
+ assert_equal categories(:child_3), categories(:top_level).children[2]
266
+ end
267
+
268
+ def test_is_or_is_ancestor_of?
269
+ assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_1))
270
+ assert categories(:top_level).is_or_is_ancestor_of?(categories(:child_2_1))
271
+ assert categories(:child_2).is_or_is_ancestor_of?(categories(:child_2_1))
272
+ assert !categories(:child_2_1).is_or_is_ancestor_of?(categories(:child_2))
273
+ assert !categories(:child_1).is_or_is_ancestor_of?(categories(:child_2))
274
+ assert categories(:child_1).is_or_is_ancestor_of?(categories(:child_1))
275
+ end
276
+
277
+ def test_is_ancestor_of?
278
+ assert categories(:top_level).is_ancestor_of?(categories(:child_1))
279
+ assert categories(:top_level).is_ancestor_of?(categories(:child_2_1))
280
+ assert categories(:child_2).is_ancestor_of?(categories(:child_2_1))
281
+ assert !categories(:child_2_1).is_ancestor_of?(categories(:child_2))
282
+ assert !categories(:child_1).is_ancestor_of?(categories(:child_2))
283
+ assert !categories(:child_1).is_ancestor_of?(categories(:child_1))
284
+ end
285
+
286
+ def test_is_or_is_ancestor_of_with_scope
287
+ root = ScopedCategory.root
288
+ child = root.children.first
289
+ assert root.is_or_is_ancestor_of?(child)
290
+ child.update_attributes :organization_id => 'different'
291
+ assert !root.is_or_is_ancestor_of?(child)
292
+ end
293
+
294
+ def test_is_or_is_descendant_of?
295
+ assert categories(:child_1).is_or_is_descendant_of?(categories(:top_level))
296
+ assert categories(:child_2_1).is_or_is_descendant_of?(categories(:top_level))
297
+ assert categories(:child_2_1).is_or_is_descendant_of?(categories(:child_2))
298
+ assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_2_1))
299
+ assert !categories(:child_2).is_or_is_descendant_of?(categories(:child_1))
300
+ assert categories(:child_1).is_or_is_descendant_of?(categories(:child_1))
301
+ end
302
+
303
+ def test_is_descendant_of?
304
+ assert categories(:child_1).is_descendant_of?(categories(:top_level))
305
+ assert categories(:child_2_1).is_descendant_of?(categories(:top_level))
306
+ assert categories(:child_2_1).is_descendant_of?(categories(:child_2))
307
+ assert !categories(:child_2).is_descendant_of?(categories(:child_2_1))
308
+ assert !categories(:child_2).is_descendant_of?(categories(:child_1))
309
+ assert !categories(:child_1).is_descendant_of?(categories(:child_1))
310
+ end
311
+
312
+ def test_is_or_is_descendant_of_with_scope
313
+ root = ScopedCategory.root
314
+ child = root.children.first
315
+ assert child.is_or_is_descendant_of?(root)
316
+ child.update_attributes :organization_id => 'different'
317
+ assert !child.is_or_is_descendant_of?(root)
318
+ end
319
+
320
+ def test_same_scope?
321
+ root = ScopedCategory.root
322
+ child = root.children.first
323
+ assert child.same_scope?(root)
324
+ child.update_attributes :organization_id => 'different'
325
+ assert !child.same_scope?(root)
326
+ end
327
+
328
+ def test_left_sibling
329
+ assert_equal categories(:child_1), categories(:child_2).left_sibling
330
+ assert_equal categories(:child_2), categories(:child_3).left_sibling
331
+ end
332
+
333
+ def test_left_sibling_of_root
334
+ assert_nil categories(:top_level).left_sibling
335
+ end
336
+
337
+ def test_left_sibling_without_siblings
338
+ assert_nil categories(:child_2_1).left_sibling
339
+ end
340
+
341
+ def test_left_sibling_of_leftmost_node
342
+ assert_nil categories(:child_1).left_sibling
343
+ end
344
+
345
+ def test_right_sibling
346
+ assert_equal categories(:child_3), categories(:child_2).right_sibling
347
+ assert_equal categories(:child_2), categories(:child_1).right_sibling
348
+ end
349
+
350
+ def test_right_sibling_of_root
351
+ assert_equal categories(:top_level_2), categories(:top_level).right_sibling
352
+ assert_nil categories(:top_level_2).right_sibling
353
+ end
354
+
355
+ def test_right_sibling_without_siblings
356
+ assert_nil categories(:child_2_1).right_sibling
357
+ end
358
+
359
+ def test_right_sibling_of_rightmost_node
360
+ assert_nil categories(:child_3).right_sibling
361
+ end
362
+
363
+ def test_move_left
364
+ categories(:child_2).move_left
365
+ assert_nil categories(:child_2).left_sibling
366
+ assert_equal categories(:child_1), categories(:child_2).right_sibling
367
+ assert Category.valid?
368
+ end
369
+
370
+ def test_move_right
371
+ categories(:child_2).move_right
372
+ assert_nil categories(:child_2).right_sibling
373
+ assert_equal categories(:child_3), categories(:child_2).left_sibling
374
+ assert Category.valid?
375
+ end
376
+
377
+ def test_move_to_left_of
378
+ categories(:child_3).move_to_left_of(categories(:child_1))
379
+ assert_nil categories(:child_3).left_sibling
380
+ assert_equal categories(:child_1), categories(:child_3).right_sibling
381
+ assert Category.valid?
382
+ end
383
+
384
+ def test_move_to_right_of
385
+ categories(:child_1).move_to_right_of(categories(:child_3))
386
+ assert_nil categories(:child_1).right_sibling
387
+ assert_equal categories(:child_3), categories(:child_1).left_sibling
388
+ assert Category.valid?
389
+ end
390
+
391
+ def test_move_to_root
392
+ categories(:child_2).move_to_root
393
+ assert_nil categories(:child_2).parent
394
+ assert_equal 0, categories(:child_2).level
395
+ assert_equal 1, categories(:child_2_1).level
396
+ assert_equal 1, categories(:child_2).left
397
+ assert_equal 4, categories(:child_2).right
398
+ assert Category.valid?
399
+ end
400
+
401
+ def test_move_to_child_of
402
+ categories(:child_1).move_to_child_of(categories(:child_3))
403
+ assert_equal categories(:child_3).id, categories(:child_1).parent_id
404
+ assert Category.valid?
405
+ end
406
+
407
+ def test_move_to_child_of_appends_to_end
408
+ child = Category.create! :name => 'New Child'
409
+ child.move_to_child_of categories(:top_level)
410
+ assert_equal child, categories(:top_level).children.last
411
+ end
412
+
413
+ def test_subtree_move_to_child_of
414
+ assert_equal 4, categories(:child_2).left
415
+ assert_equal 7, categories(:child_2).right
416
+
417
+ assert_equal 2, categories(:child_1).left
418
+ assert_equal 3, categories(:child_1).right
419
+
420
+ categories(:child_2).move_to_child_of(categories(:child_1))
421
+ assert Category.valid?
422
+ assert_equal categories(:child_1).id, categories(:child_2).parent_id
423
+
424
+ assert_equal 3, categories(:child_2).left
425
+ assert_equal 6, categories(:child_2).right
426
+ assert_equal 2, categories(:child_1).left
427
+ assert_equal 7, categories(:child_1).right
428
+ end
429
+
430
+ def test_slightly_difficult_move_to_child_of
431
+ assert_equal 11, categories(:top_level_2).left
432
+ assert_equal 12, categories(:top_level_2).right
433
+
434
+ # create a new top-level node and move single-node top-level tree inside it.
435
+ new_top = Category.create(:name => 'New Top')
436
+ assert_equal 13, new_top.left
437
+ assert_equal 14, new_top.right
438
+
439
+ categories(:top_level_2).move_to_child_of(new_top)
440
+
441
+ assert Category.valid?
442
+ assert_equal new_top.id, categories(:top_level_2).parent_id
443
+
444
+ assert_equal 12, categories(:top_level_2).left
445
+ assert_equal 13, categories(:top_level_2).right
446
+ assert_equal 11, new_top.left
447
+ assert_equal 14, new_top.right
448
+ end
449
+
450
+ def test_difficult_move_to_child_of
451
+ assert_equal 1, categories(:top_level).left
452
+ assert_equal 10, categories(:top_level).right
453
+ assert_equal 5, categories(:child_2_1).left
454
+ assert_equal 6, categories(:child_2_1).right
455
+
456
+ # create a new top-level node and move an entire top-level tree inside it.
457
+ new_top = Category.create(:name => 'New Top')
458
+ categories(:top_level).move_to_child_of(new_top)
459
+ categories(:child_2_1).reload
460
+ assert Category.valid?
461
+ assert_equal new_top.id, categories(:top_level).parent_id
462
+
463
+ assert_equal 4, categories(:top_level).left
464
+ assert_equal 13, categories(:top_level).right
465
+ assert_equal 8, categories(:child_2_1).left
466
+ assert_equal 9, categories(:child_2_1).right
467
+ end
468
+
469
+ #rebuild swaps the position of the 2 children when added using move_to_child twice onto same parent
470
+ def test_move_to_child_more_than_once_per_parent_rebuild
471
+ root1 = Category.create(:name => 'Root1')
472
+ root2 = Category.create(:name => 'Root2')
473
+ root3 = Category.create(:name => 'Root3')
474
+
475
+ root2.move_to_child_of root1
476
+ root3.move_to_child_of root1
477
+
478
+ output = Category.roots.last.to_text
479
+ Category.collection.update({}, { :lft => nil, :rgt => nil }, :multi => true)
480
+ Category.rebuild!
481
+
482
+ assert_equal Category.roots.last.to_text, output
483
+ end
484
+
485
+ # doing move_to_child twice onto same parent from the furthest right first
486
+ def test_move_to_child_more_than_once_per_parent_outside_in
487
+ node1 = Category.create(:name => 'Node-1')
488
+ node2 = Category.create(:name => 'Node-2')
489
+ node3 = Category.create(:name => 'Node-3')
490
+
491
+ node2.move_to_child_of node1
492
+ node3.move_to_child_of node1
493
+
494
+ output = Category.roots.last.to_text
495
+ Category.collection.update({}, { :lft => nil, :rgt => nil }, :multi => true)
496
+ Category.rebuild!
497
+
498
+ assert_equal Category.roots.last.to_text, output
499
+ end
500
+
501
+ # def test_valid_with_null_lefts
502
+ # assert Category.valid?
503
+ # Category.collection.update({}, { :lft => nil }, :multi => true)
504
+ # assert !Category.valid?
505
+ # end
506
+ #
507
+ # def test_valid_with_null_rights
508
+ # assert Category.valid?
509
+ # Category.collection.update({}, { :rgt => nil }, :multi => true)
510
+ # assert !Category.valid?
511
+ # end
512
+
513
+ def test_valid_with_missing_intermediate_node
514
+ # Even though child_2_1 will still exist, it is a sign of a sloppy delete, not an invalid tree.
515
+ assert Category.valid?
516
+ Category.delete(categories(:child_2).id)
517
+ assert Category.valid?
518
+ end
519
+
520
+ def test_valid_with_overlapping_and_rights
521
+ assert Category.valid?
522
+ categories(:top_level_2)['lft'] = 0
523
+ categories(:top_level_2).save
524
+ assert !Category.valid?
525
+ end
526
+
527
+ def test_rebuild
528
+ assert Category.valid?
529
+ before_text = Category.root.to_text
530
+ Category.collection.update({}, { :lft => nil, :rgt => nil }, :multi => true)
531
+ Category.rebuild!
532
+ assert Category.valid?
533
+ assert_equal before_text, Category.root.to_text
534
+ end
535
+
536
+ def test_move_possible_for_sibling
537
+ assert categories(:child_2).move_possible?(categories(:child_1))
538
+ end
539
+
540
+ def test_move_not_possible_to_self
541
+ assert !categories(:top_level).move_possible?(categories(:top_level))
542
+ end
543
+
544
+ def test_move_not_possible_to_parent
545
+ categories(:top_level).descendants.each do |descendant|
546
+ assert !categories(:top_level).move_possible?(descendant)
547
+ assert descendant.move_possible?(categories(:top_level))
548
+ end
549
+ end
550
+
551
+ def test_is_or_is_ancestor_of?
552
+ [:child_1, :child_2, :child_2_1, :child_3].each do |c|
553
+ assert categories(:top_level).is_or_is_ancestor_of?(categories(c))
554
+ end
555
+ assert !categories(:top_level).is_or_is_ancestor_of?(categories(:top_level_2))
556
+ end
557
+
558
+ def test_left_and_rights_valid_with_blank_left
559
+ assert Category.left_and_rights_valid?
560
+ categories(:child_2)[:lft] = nil
561
+ categories(:child_2).save(:validate => false)
562
+ assert !Category.left_and_rights_valid?
563
+ end
564
+
565
+ def test_left_and_rights_valid_with_blank_right
566
+ assert Category.left_and_rights_valid?
567
+ categories(:child_2)[:rgt] = nil
568
+ categories(:child_2).save(:validate => false)
569
+ assert !Category.left_and_rights_valid?
570
+ end
571
+
572
+ def test_left_and_rights_valid_with_equal
573
+ assert Category.left_and_rights_valid?
574
+ categories(:top_level_2)[:lft] = categories(:top_level_2)[:rgt]
575
+ categories(:top_level_2).save(:validate => false)
576
+ assert !Category.left_and_rights_valid?
577
+ end
578
+
579
+ def test_left_and_rights_valid_with_left_equal_to_parent
580
+ assert Category.left_and_rights_valid?
581
+ categories(:child_2)[:lft] = categories(:top_level)[:lft]
582
+ categories(:child_2).save(:validate => false)
583
+ assert !Category.left_and_rights_valid?
584
+ end
585
+
586
+ def test_left_and_rights_valid_with_right_equal_to_parent
587
+ assert Category.left_and_rights_valid?
588
+ categories(:child_2)[:rgt] = categories(:top_level)[:rgt]
589
+ categories(:child_2).save(:validate => false)
590
+ assert !Category.left_and_rights_valid?
591
+ end
592
+
593
+ def test_moving_dirty_objects_doesnt_invalidate_tree
594
+ r1 = Category.create
595
+ r2 = Category.create
596
+ r3 = Category.create
597
+ r4 = Category.create
598
+ nodes = [r1, r2, r3, r4]
599
+
600
+ r2.move_to_child_of(r1)
601
+ assert Category.valid?
602
+
603
+ r3.move_to_child_of(r1)
604
+ assert Category.valid?
605
+
606
+ r4.move_to_child_of(r2)
607
+ assert Category.valid?
608
+ end
609
+
610
+ def test_multi_scoped_no_duplicates_for_columns?
611
+ assert_nothing_raised do
612
+ Note.no_duplicates_for_columns?
613
+ end
614
+ end
615
+
616
+ def test_multi_scoped_all_roots_valid?
617
+ assert_nothing_raised do
618
+ Note.all_roots_valid?
619
+ end
620
+ end
621
+
622
+ def test_multi_scoped
623
+ note1 = Note.create!(:body => "A", :notable_id => 2, :notable_type => 'Category')
624
+ note2 = Note.create!(:body => "B", :notable_id => 2, :notable_type => 'Category')
625
+ note3 = Note.create!(:body => "C", :notable_id => 2, :notable_type => 'Default')
626
+
627
+ assert_equal [note1, note2], note1.self_and_siblings
628
+ assert_equal [note3], note3.self_and_siblings
629
+ end
630
+
631
+ def test_multi_scoped_rebuild
632
+ root = Note.create!(:body => "A", :notable_id => 3, :notable_type => 'Category')
633
+ child1 = Note.create!(:body => "B", :notable_id => 3, :notable_type => 'Category')
634
+ child2 = Note.create!(:body => "C", :notable_id => 3, :notable_type => 'Category')
635
+
636
+ child1.move_to_child_of root
637
+ child2.move_to_child_of root
638
+
639
+ Note.collection.update({}, { :lft => nil, :rgt => nil }, :multi => true)
640
+ Note.rebuild!
641
+
642
+ assert_equal Note.find(:first, :parent_id => nil, :body => 'A'), root
643
+ assert_equal [child1, child2], Note.find(:first, :parent_id => nil, :body => 'A').children
644
+ end
645
+
646
+ def test_same_scope_with_multi_scopes
647
+ assert_nothing_raised do
648
+ notes(:scope1).same_scope?(notes(:child_1))
649
+ end
650
+ assert notes(:scope1).same_scope?(notes(:child_1))
651
+ assert notes(:child_1).same_scope?(notes(:scope1))
652
+ assert !notes(:scope1).same_scope?(notes(:scope2))
653
+ end
654
+
655
+ # def test_quoting_of_multi_scope_column_names
656
+ # assert_equal ["\"notable_id\"", "\"notable_type\""], Note.quoted_scope_column_names
657
+ # end
658
+
659
+ def test_equal_in_same_scope
660
+ assert_equal notes(:scope1), notes(:scope1)
661
+ assert_not_equal notes(:scope1), notes(:child_1)
662
+ end
663
+
664
+ def test_equal_in_different_scopes
665
+ assert_not_equal notes(:scope1), notes(:scope2)
666
+ end
667
+
668
+ def test_delete_does_not_invalidate
669
+ Category.acts_as_nested_set_options[:dependent] = :delete
670
+ categories(:child_2).destroy
671
+ assert Category.valid?
672
+ end
673
+
674
+ def test_destroy_does_not_invalidate
675
+ Category.acts_as_nested_set_options[:dependent] = :destroy
676
+ categories(:child_2).destroy
677
+ assert Category.valid?
678
+ end
679
+
680
+ def test_destroy_multiple_times_does_not_invalidate
681
+ Category.acts_as_nested_set_options[:dependent] = :destroy
682
+ categories(:child_2).destroy
683
+ categories(:child_2).destroy
684
+ assert Category.valid?
685
+ end
686
+
687
+ def test_assigning_parent_id_on_create
688
+ category = Category.create!(:name => "Child", :parent_id => categories(:child_2).id)
689
+ assert_equal categories(:child_2), category.parent
690
+ assert_equal categories(:child_2).id, category.parent_id
691
+ assert_not_nil category.left
692
+ assert_not_nil category.right
693
+ assert Category.valid?
694
+ end
695
+
696
+ def test_assigning_parent_on_create
697
+ category = Category.create!(:name => "Child", :parent => categories(:child_2))
698
+ assert_equal categories(:child_2), category.parent
699
+ assert_equal categories(:child_2).id, category.parent_id
700
+ assert_not_nil category.left
701
+ assert_not_nil category.right
702
+ assert Category.valid?
703
+ end
704
+
705
+ def test_assigning_parent_id_to_nil_on_create
706
+ category = Category.create!(:name => "New Root", :parent_id => nil)
707
+ assert_nil category.parent
708
+ assert_nil category.parent_id
709
+ assert_not_nil category.left
710
+ assert_not_nil category.right
711
+ assert Category.valid?
712
+ end
713
+
714
+ def test_assigning_parent_id_on_update
715
+ category = categories(:child_2_1)
716
+ category.parent_id = categories(:child_3).id
717
+ category.save
718
+ assert_equal categories(:child_3), category.parent
719
+ assert_equal categories(:child_3).id, category.parent_id
720
+ assert Category.valid?
721
+ end
722
+
723
+ def test_assigning_parent_on_update
724
+ category = categories(:child_2_1)
725
+ category.parent = categories(:child_3)
726
+ category.save
727
+ assert_equal categories(:child_3), category.parent
728
+ assert_equal categories(:child_3).id, category.parent_id
729
+ assert Category.valid?
730
+ end
731
+
732
+ def test_assigning_parent_id_to_nil_on_update
733
+ category = categories(:child_2_1)
734
+ category.parent_id = nil
735
+ category.save
736
+ assert_nil category.parent
737
+ assert_nil category.parent_id
738
+ assert Category.valid?
739
+ end
740
+
741
+ def test_creating_child_from_parent
742
+ category = categories(:child_2).children.create!(:name => "Child")
743
+ assert_equal categories(:child_2), category.parent
744
+ assert_equal categories(:child_2).id, category.parent_id
745
+ assert_not_nil category.left
746
+ assert_not_nil category.right
747
+ assert Category.valid?
748
+ end
749
+
750
+ def check_structure(entries, structure)
751
+ structure = structure.dup
752
+ Category.each_with_level(entries) do |category, level|
753
+ expected_level, expected_name = structure.shift
754
+ assert_equal expected_name, category.name, "wrong category"
755
+ assert_equal expected_level, level, "wrong level for #{category.name}"
756
+ end
757
+ end
758
+
759
+ def test_each_with_level
760
+ levels = [
761
+ [0, "Top Level"],
762
+ [1, "Child 1"],
763
+ [1, "Child 2"],
764
+ [2, "Child 2.1"],
765
+ [1, "Child 3" ]]
766
+
767
+ check_structure(Category.root.self_and_descendants, levels)
768
+
769
+ # test some deeper structures
770
+ category = Category.find_by_name("Child 1")
771
+ c1 = Category.new(:name => "Child 1.1")
772
+ c2 = Category.new(:name => "Child 1.1.1")
773
+ c3 = Category.new(:name => "Child 1.1.1.1")
774
+ c4 = Category.new(:name => "Child 1.2")
775
+ [c1, c2, c3, c4].each(&:save!)
776
+
777
+ c1.move_to_child_of(category)
778
+ c2.move_to_child_of(c1)
779
+ c3.move_to_child_of(c2)
780
+ c4.move_to_child_of(category)
781
+
782
+ levels = [
783
+ [0, "Top Level"],
784
+ [1, "Child 1"],
785
+ [2, "Child 1.1"],
786
+ [3, "Child 1.1.1"],
787
+ [4, "Child 1.1.1.1"],
788
+ [2, "Child 1.2"],
789
+ [1, "Child 2"],
790
+ [2, "Child 2.1"],
791
+ [1, "Child 3" ]]
792
+
793
+ check_structure(Category.root.self_and_descendants, levels)
794
+ end
795
+ end