mongoid-tree-rational 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,765 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::Tree::RationalNumbering do
4
+
5
+ subject { RationalNumberedNode }
6
+
7
+ it "should verify type of initial rational numbers" do
8
+ f_nv = RationalNumberedNode.fields['rational_number_nv']
9
+ f_dv = RationalNumberedNode.fields['rational_number_dv']
10
+ f_snv = RationalNumberedNode.fields['rational_number_snv']
11
+ f_sdv = RationalNumberedNode.fields['rational_number_sdv']
12
+ f_value = RationalNumberedNode.fields['rational_number_value']
13
+ expect(f_nv).not_to be_nil
14
+ expect(f_nv.options[:type]).to eq(Integer)
15
+ expect(f_dv).not_to be_nil
16
+ expect(f_dv.options[:type]).to eq(Integer)
17
+ expect(f_snv).not_to be_nil
18
+ expect(f_snv.options[:type]).to eq(Integer)
19
+ expect(f_sdv).not_to be_nil
20
+ expect(f_sdv.options[:type]).to eq(Integer)
21
+ expect(f_value).not_to be_nil
22
+ expect(f_value.options[:type]).to eq(BigDecimal)
23
+ end
24
+
25
+ it 'should have same numbers as in the paper for rational number in nested sets theory' do
26
+ setup_tree <<-ENDTREE
27
+ - node_1
28
+ - node_2:
29
+ - node_2_1
30
+ - node_2_2
31
+ - node_2_3
32
+ - node_2_4:
33
+ - node_2_4_1
34
+ - node_2_4_2
35
+ - node_2_4_3
36
+ ENDTREE
37
+
38
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(1,1))
39
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(2,1))
40
+ expect(node(:node_2_1).rational_number).to eq(RationalNumber.new(5,2))
41
+ expect(node(:node_2_2).rational_number).to eq(RationalNumber.new(8,3))
42
+ expect(node(:node_2_3).rational_number).to eq(RationalNumber.new(11,4))
43
+ expect(node(:node_2_4).rational_number).to eq(RationalNumber.new(14,5))
44
+ expect(node(:node_2_4_1).rational_number).to eq(RationalNumber.new(31,11))
45
+ expect(node(:node_2_4_2).rational_number).to eq(RationalNumber.new(48,17))
46
+ expect(node(:node_2_4_3).rational_number).to eq(RationalNumber.new(65,23))
47
+ end
48
+
49
+ describe "for roots" do
50
+ it "should create a root node with initial rational numbers" do
51
+ a = RationalNumberedNode.create(:name => "a")
52
+ expect(a.rational_number).to eq(RationalNumber.new(1,1,2,1))
53
+ end
54
+
55
+ it "should create two root nodes with initial rational numbers" do
56
+ a = RationalNumberedNode.create(:name => "a")
57
+ expect(a.rational_number).to eq(RationalNumber.new(1,1,2,1))
58
+ b = RationalNumberedNode.create(:name => "b")
59
+ expect(b.rational_number).to eq(RationalNumber.new(2,1,3,1))
60
+ end
61
+ end
62
+
63
+
64
+ describe "when setting parent/children" do
65
+
66
+ it "should set the parent of a node after creating the object" do
67
+ a = RationalNumberedNode.create(:name => "a")
68
+ b = RationalNumberedNode.create(:name => "b")
69
+ b.parent = a
70
+ b.save!
71
+ expect(a.rational_number).to eq(RationalNumber.new(1,1,2,1))
72
+ expect(b.rational_number).to eq(RationalNumber.new(3,2,5,3))
73
+ end
74
+
75
+ # TODO
76
+ # it "should set the parent when creating the object" do
77
+ # end
78
+
79
+ it "should add children to an existing node" do
80
+ a = RationalNumberedNode.create(:name => "a")
81
+ b = RationalNumberedNode.create(:name => "b")
82
+ a.children << b
83
+ expect(a.rational_number).to eq(RationalNumber.new(1,1,2,1))
84
+ expect(b.rational_number).to eq(RationalNumber.new(3,2,5,3))
85
+ end
86
+ end
87
+
88
+ describe 'when saved' do
89
+ before(:each) do
90
+
91
+ setup_tree <<-ENDTREE
92
+ - node_1:
93
+ - node_1_1:
94
+ - node_1_1_1:
95
+ - node_1_1_1_1
96
+ - node_1_2
97
+ - node_1_3
98
+ - node_2:
99
+ - node_2_1
100
+ - node_2_2
101
+ ENDTREE
102
+ end
103
+
104
+ it "should assign a rational number to each node" do
105
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(1,1,2,1))
106
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(2,1,3,1))
107
+ expect(node(:node_1_1).rational_number).to eq(RationalNumber.new(3,2,5,3))
108
+ expect(node(:node_1_2).rational_number).to eq(RationalNumber.new(5,3,7,4))
109
+ expect(node(:node_2_1).rational_number).to eq(RationalNumber.new(5,2,8,3))
110
+ expect(node(:node_2_2).rational_number).to eq(RationalNumber.new(8,3,11,4))
111
+ end
112
+
113
+ it "should get the position for each of the nodes" do
114
+ expect(node(:node_1).position).to eq(1)
115
+ expect(node(:node_1_1).position).to eq(1)
116
+ expect(node(:node_1_2).position).to eq(2)
117
+ end
118
+
119
+ it "should move a node to the end of a list when it is moved to a new parent" do
120
+ original_root = node(:node_1)
121
+ other_root = node(:node_2)
122
+ child = node(:node_1_2)
123
+ expect(child.position).to eq(2)
124
+ child.parent = other_root
125
+ child.save
126
+ child.reload
127
+ expect(child.position).to eq(3)
128
+ end
129
+
130
+ it "should correctly reposition siblings when one of them is removed" do
131
+ rational_node_1_1 = node(:node_1_1).rational_number
132
+ node(:node_1_1).destroy
133
+ expect(node(:node_1_2).position).to eq(1)
134
+ expect(node(:node_1_2).rational_number).to eq(RationalNumber.new(3,2,5,3))
135
+ end
136
+
137
+ it "should correctly reposition siblings when one of them is added as a child of another parent" do
138
+ node(:node_2).children << node(:node_1_1)
139
+ expect(node(:node_1_2).position).to eq(1)
140
+ expect(node(:node_1_2).rational_number).to eq(RationalNumber.new(3,2,5,3))
141
+ end
142
+
143
+ it "should correctly reposition siblings when the parent is changed" do
144
+ n = node(:node_1_1)
145
+ n.parent = node(:node_2)
146
+ n.save!
147
+ expect(node(:node_1_2).position).to eq(1)
148
+ expect(node(:node_1_2).rational_number).to eq(RationalNumber.new(3,2,5,3))
149
+ end
150
+
151
+ it "should not reposition siblings when it's not needed" do
152
+ new_node = RationalNumberedNode.new(:name => 'new')
153
+ new_node.parent = node(:node_1)
154
+ expect(new_node).not_to receive(:rekey_former_siblings)
155
+ new_node.save!
156
+ end
157
+
158
+ end
159
+
160
+ describe 'destroy strategies' do
161
+ # before(:each) do
162
+ # setup_tree <<-ENDTREE
163
+ # - root:
164
+ # - child:
165
+ # - subchild
166
+ # - other_child
167
+ # - other_root
168
+ # ENDTREE
169
+ # end
170
+
171
+ # describe ':move_children_to_parent' do
172
+ # it "should set its childen's parent_id to the documents parent_id" do
173
+ # node(:child).move_children_to_parent
174
+ # node(:child).should be_leaf
175
+ # node(:root).children.to_a.should == [node(:child), node(:other_child), node(:subchild)]
176
+ # end
177
+ # end
178
+ end
179
+
180
+ describe 'utility methods' do
181
+ before(:each) do
182
+ setup_tree <<-ENDTREE
183
+ - node_1:
184
+ - node_1_1:
185
+ - node_1_1_1:
186
+ - node_1_1_1_1
187
+ - node_1_2
188
+ - node_1_3
189
+ - node_2:
190
+ - node_2_1
191
+ - node_2_2
192
+ - node_3
193
+ ENDTREE
194
+ end
195
+
196
+ describe '#lower_siblings' do
197
+ it "should return a collection of siblings lower on the list" do
198
+ expect(node(:node_1).lower_siblings.to_a).to eq([node(:node_2), node(:node_3)])
199
+ expect(node(:node_2).lower_siblings.to_a).to eq([node(:node_3)])
200
+ expect(node(:node_3).lower_siblings.to_a).to eq([])
201
+ expect(node(:node_1_1).lower_siblings.to_a).to eq([node(:node_1_2), node(:node_1_3)])
202
+ expect(node(:node_2_2).lower_siblings.to_a).to eq([])
203
+ expect(node(:node_1_1_1).lower_siblings.to_a).to eq([])
204
+ expect(node(:node_1_1_1_1).lower_siblings.to_a).to eq([])
205
+ end
206
+ end
207
+
208
+ describe '#higher_siblings' do
209
+ it "should return a collection of siblings lower on the list" do
210
+ expect(node(:node_1).higher_siblings.to_a).to eq([])
211
+ expect(node(:node_2).higher_siblings.to_a).to eq([node(:node_1)])
212
+ expect(node(:node_3).higher_siblings.to_a).to eq([node(:node_1), node(:node_2)])
213
+ expect(node(:node_1_1).higher_siblings.to_a).to eq([])
214
+ expect(node(:node_1_2).higher_siblings.to_a).to eq([node(:node_1_1)])
215
+ end
216
+ end
217
+
218
+ describe '#at_top?' do
219
+ it "should return true when the node is first in the list" do
220
+ expect(node(:node_1)).to be_at_top
221
+ expect(node(:node_1_1)).to be_at_top
222
+ end
223
+
224
+ it "should return false when the node is not first in the list" do
225
+ expect(node(:node_2)).not_to be_at_top
226
+ expect(node(:node_3)).not_to be_at_top
227
+ expect(node(:node_1_2)).not_to be_at_top
228
+ end
229
+ end
230
+
231
+ describe '#at_bottom?' do
232
+ it "should return true when the node is last in the list" do
233
+ expect(node(:node_3)).to be_at_bottom
234
+ expect(node(:node_1_3)).to be_at_bottom
235
+ end
236
+
237
+ it "should return false when the node is not last in the list" do
238
+ expect(node(:node_1)).not_to be_at_bottom
239
+ expect(node(:node_2)).not_to be_at_bottom
240
+ expect(node(:node_1_1)).not_to be_at_bottom
241
+ end
242
+ end
243
+
244
+ describe '#last_sibling_in_list' do
245
+ it "should return the last sibling in the list containing the current sibling" do
246
+ expect(node(:node_1).last_sibling_in_list).to eq(node(:node_3))
247
+ expect(node(:node_2).last_sibling_in_list).to eq(node(:node_3))
248
+ expect(node(:node_3).last_sibling_in_list).to eq(node(:node_3))
249
+ end
250
+ end
251
+
252
+ describe '#first_sibling_in_list' do
253
+ it "should return the first sibling in the list containing the current sibling" do
254
+ expect(node(:node_1).first_sibling_in_list).to eq(node(:node_1))
255
+ expect(node(:node_2).first_sibling_in_list).to eq(node(:node_1))
256
+ expect(node(:node_3).first_sibling_in_list).to eq(node(:node_1))
257
+ end
258
+ end
259
+
260
+ describe '#ancestors' do
261
+ it "should be returned in the correct order" do
262
+ setup_tree <<-ENDTREE
263
+ - root:
264
+ - level_1_a
265
+ - level_1_b:
266
+ - level_2_a:
267
+ - leaf
268
+ ENDTREE
269
+
270
+ expect(node(:leaf).ancestors.to_a).to eq([node(:root), node(:level_1_b), node(:level_2_a)])
271
+ end
272
+
273
+ it "should return the ancestors in correct order after rearranging" do
274
+ setup_tree <<-ENDTREE
275
+ - node_1:
276
+ - node_1_1:
277
+ - node_1_1_1
278
+ ENDTREE
279
+
280
+ node_1_1 = node(:node_1_1)
281
+ node_1_1.parent = nil
282
+ node_1_1.save!
283
+
284
+ node_1 = node(:node_1)
285
+ node_1.parent = node(:node_1_1)
286
+ node_1.save!
287
+
288
+ node_1_1_1 = node(:node_1_1_1)
289
+ node_1_1_1.parent = node_1
290
+ node_1_1_1.save!
291
+
292
+ expect(node_1_1_1.ancestors.to_a).to eq([node_1_1, node_1])
293
+ end
294
+ end
295
+ end
296
+
297
+ describe 'moving nodes with large tree' do
298
+ before(:each) do
299
+
300
+ # setup_tree <<-ENDTREE
301
+ # - node_1:
302
+ # - node_1_1:
303
+ # - node_1_1_1:
304
+ # - node_1_1_1_1
305
+ # - node_1_2
306
+ # - node_1_3
307
+ # - node_2:
308
+ # - node_2_1
309
+ # - node_2_2
310
+ # - node_3
311
+ # ENDTREE
312
+
313
+ setup_tree <<-ENDTREE
314
+ - node_1:
315
+ - node_1_1
316
+ - node_1_2:
317
+ - node_1_2_1:
318
+ - node_1_2_1_1
319
+ - node_1_2_1_2
320
+ - node_1_2_2:
321
+ - node_1_2_2_1
322
+ - node_1_2_2_2
323
+ - node_1_2_2_3
324
+ - node_2:
325
+ - node_2_1
326
+ - node_2_2
327
+ - node_2_3
328
+ - node_2_4:
329
+ - node_2_4_1
330
+ - node_2_4_2
331
+ - node_2_4_3
332
+ - node_3:
333
+ - node_3_1
334
+ - node_3_2
335
+ - node_3_3
336
+ ENDTREE
337
+ end
338
+
339
+ describe '#move_below' do
340
+
341
+ it 'should verify rational numbers after moving' do
342
+ expect(node(:node_1).position).to eq(1)
343
+ expect(node(:node_2).position).to eq(2)
344
+ expect(node(:node_3).position).to eq(3)
345
+ node_to_move = node(:node_1)
346
+ node_to_move.move_below(node(:node_2))
347
+ expect(node(:node_1).position).to eq(2)
348
+ expect(node(:node_2).position).to eq(1)
349
+ expect(node(:node_3).position).to eq(3)
350
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(2,1))
351
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(1,1))
352
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(3,1))
353
+ end
354
+
355
+ it 'should fix positions within the current list when moving an sibling away from its current parent' do
356
+ node_to_move = node(:node_1_1)
357
+ node_to_move.move_below(node(:node_2_1))
358
+ expect(node(:node_1_2).position).to eq(1)
359
+ expect(node(:node_1_2).rational_number).to eq(RationalNumber.new(3,2))
360
+ end
361
+
362
+ it 'should work when moving to a different parent' do
363
+ node_to_move = node(:node_1_1)
364
+ new_parent = node(:node_2)
365
+ node_to_move.move_below(node(:node_2_1))
366
+ node_to_move.reload
367
+ expect(node_to_move.position).to eq(2)
368
+ # expect(node_to_move.rational_number).to eq(RationalNumber.new(14,5))
369
+ # expect(node(:node_2_1).rational_number).to eq(RationalNumber.new(17,6))
370
+ expect(node(:node_1_2)).to be_at_top
371
+ expect(node(:node_2_1)).to be_at_top
372
+ end
373
+
374
+ it 'should be able to move the first node below the second node' do
375
+ first_node = node(:node_1)
376
+ second_node = node(:node_2)
377
+ first_node.move_below(second_node)
378
+ first_node.reload
379
+ second_node.reload
380
+ expect(second_node).to be_at_top
381
+ expect(first_node.higher_siblings.to_a).to eq([second_node])
382
+ end
383
+
384
+ it 'should be able to move the last node below the first node' do
385
+ first_node = node(:node_1)
386
+ last_node = node(:node_3)
387
+ last_node.move_below(first_node)
388
+ first_node.reload
389
+ last_node.reload
390
+ expect(last_node).not_to be_at_bottom
391
+ expect(node(:node_2)).to be_at_bottom
392
+ expect(last_node.higher_siblings.to_a).to eq([first_node])
393
+ end
394
+
395
+ it 'should rekey the children of a node when moving to a new parent' do
396
+ node_1_2_1_prev_keys = node(:node_1_2_1).rational_number
397
+ node_1_2_1_2_prev_keys = node(:node_1_2_1_2).rational_number
398
+ node_2_4_1_prev_keys = node(:node_2_4_1).rational_number
399
+ node_2_4_2_prev_keys = node(:node_2_4_2).rational_number
400
+ node_1_2 = node(:node_1_2)
401
+ node_1_2.move_below(node(:node_2_3))
402
+
403
+ expect(node(:node_1_2_1).rational_number).not_to eq(node_1_2_1_prev_keys)
404
+ expect(node(:node_1_2_1_2).rational_number).not_to eq(node_1_2_1_2_prev_keys)
405
+
406
+ # As these takes "over" the positions for former nodes, check equality of previous positions
407
+ expect(node(:node_1_2_1).rational_number).to eq(node_2_4_1_prev_keys)
408
+ expect(node(:node_1_2_2).rational_number).to eq(node_2_4_2_prev_keys)
409
+ expect(node(:node_1_2_1_2).rational_number).to eq(RationalNumber.new(127,45))
410
+ end
411
+ end
412
+
413
+ describe '#move_above' do
414
+ it 'should verify rational numbers after moving' do
415
+ expect(node(:node_1).position).to eq(1)
416
+ expect(node(:node_2).position).to eq(2)
417
+ expect(node(:node_3).position).to eq(3)
418
+ node_to_move = node(:node_1)
419
+ node_to_move.move_above(node(:node_3))
420
+ expect(node(:node_1).position).to eq(2)
421
+ expect(node(:node_2).position).to eq(1)
422
+ expect(node(:node_3).position).to eq(3)
423
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(2,1))
424
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(1,1))
425
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(3,1))
426
+ end
427
+
428
+ it 'should fix positions within the current list when moving an sibling away from its current parent' do
429
+ node_to_move = node(:node_1_1)
430
+ node_to_move.move_above(node(:node_2_1))
431
+ expect(node(:node_1_2).position).to eq(1)
432
+ expect(node(:node_1_1).position).to eq(1)
433
+ expect(node(:node_2_1).position).to eq(2)
434
+ end
435
+
436
+ it 'should work when moving to a different parent' do
437
+ # store children rational numbers before move
438
+ node_to_move = node(:node_1_1)
439
+ node_to_move.move_above(node(:node_2_4))
440
+ node_to_move.reload
441
+ expect(node_to_move.position).to eq(4)
442
+ expect(node_to_move.rational_number).to eq(RationalNumber.new(14,5))
443
+ expect(node(:node_2_4).rational_number).to eq(RationalNumber.new(17,6))
444
+ expect(node(:node_2_4)).to be_at_bottom
445
+ end
446
+
447
+ it 'should move children when a node is moved due to insert of another node above' do
448
+ # store children rational numbers before move
449
+ expect(node(:node_2_4_1).rational_number).to eq(RationalNumber.new(31,11))
450
+ expect(node(:node_2_4_2).rational_number).to eq(RationalNumber.new(48,17))
451
+ expect(node(:node_2_4_3).rational_number).to eq(RationalNumber.new(65,23))
452
+ prev_2_4_1 = node(:node_2_4_1).rational_number
453
+ prev_2_4_2 = node(:node_2_4_2).rational_number
454
+ prev_2_4_3 = node(:node_2_4_3).rational_number
455
+ node_to_move = node(:node_1_1)
456
+ node_to_move.move_above(node(:node_2_4))
457
+ node_to_move.reload
458
+
459
+ # verify that children of 2.4 is moved to new position
460
+ expect(node(:node_2_4_1).rational_number).not_to eq(prev_2_4_1)
461
+ expect(node(:node_2_4_2).rational_number).not_to eq(prev_2_4_2)
462
+ expect(node(:node_2_4_3).rational_number).not_to eq(prev_2_4_3)
463
+
464
+ expect(node(:node_2_4_1).rational_number).to eq(RationalNumber.new(37,13))
465
+ expect(node(:node_2_4_2).rational_number).to eq(RationalNumber.new(57,20))
466
+ expect(node(:node_2_4_3).rational_number).to eq(RationalNumber.new(77,27))
467
+ end
468
+
469
+ it 'should be able to move the last node above the second node' do
470
+ last_node = node(:node_3)
471
+ second_node = node(:node_2)
472
+ last_node.move_above(second_node)
473
+ last_node.reload
474
+ second_node.reload
475
+ expect(second_node).to be_at_bottom
476
+ expect(last_node.higher_siblings.to_a).to eq([node(:node_1)])
477
+ end
478
+
479
+ it 'should be able to move the first node above the last node' do
480
+ first_node = node(:node_1)
481
+ last_node = node(:node_3)
482
+ first_node.move_above(last_node)
483
+ first_node.reload
484
+ last_node.reload
485
+ expect(node(:node_2)).to be_at_top
486
+ expect(first_node.higher_siblings.to_a).to eq([node(:node_2)])
487
+ end
488
+
489
+ it 'should rekey the children of a node when moving to a new parent' do
490
+ node_1_2_1_prev_keys = node(:node_1_2_1).rational_number
491
+ node_1_2_1_2_prev_keys = node(:node_1_2_1_2).rational_number
492
+ node_2_4_1_prev_keys = node(:node_2_4_1).rational_number
493
+ node_2_4_2_prev_keys = node(:node_2_4_2).rational_number
494
+ node_1_2 = node(:node_1_2)
495
+ node_1_2.move_above(node(:node_2_4))
496
+
497
+ expect(node(:node_1_2_1).rational_number).not_to eq(node_1_2_1_prev_keys)
498
+ expect(node(:node_1_2_1_2).rational_number).not_to eq(node_1_2_1_2_prev_keys)
499
+
500
+ # As these takes "over" the positions for former nodes, check equality of previous positions
501
+ expect(node(:node_1_2_1).rational_number).to eq(node_2_4_1_prev_keys)
502
+ expect(node(:node_1_2_2).rational_number).to eq(node_2_4_2_prev_keys)
503
+ expect(node(:node_1_2_1_2).rational_number).to eq(RationalNumber.new(127,45))
504
+ end
505
+ end
506
+ end # moving nodes with large tree
507
+
508
+ describe 'moving nodes with small tree' do
509
+ before(:each) do
510
+
511
+ setup_tree <<-ENDTREE
512
+ - node_1:
513
+ - node_1_1
514
+ - node_1_2
515
+ - node_2:
516
+ - node_2_1
517
+ - node_2_2
518
+ - node_2_3
519
+ - node_2_4:
520
+ - node_2_4_1
521
+ - node_2_4_2
522
+ - node_2_4_3
523
+ - node_3
524
+ ENDTREE
525
+ end
526
+
527
+ # THIS IS NOT IMPLEMENTED, as it should NOT be used this way
528
+ describe "setting position or nv/dv values directly" do
529
+ it "should move conflicting nodes and their children when using attribs to set nv/dv (first test)" do
530
+ node_2_1 = node(:node_2_1)
531
+ node_2_1.rational_number_nv = 2
532
+ node_2_1.rational_number_dv = 1
533
+ node_2_1.save!
534
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(1,1))
535
+ expect(node(:node_2_1).rational_number).to eq(RationalNumber.new(2,1))
536
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(3,1))
537
+ expect(node(:node_2_2).rational_number).to eq(RationalNumber.new(7,2))
538
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(4,1))
539
+ end
540
+
541
+ it "should move conflicting nodes and their children when using attribs to set nv/dv (second test)" do
542
+ node_2_1 = node(:node_2_1)
543
+ node_2_1.rational_number_nv = 1
544
+ node_2_1.rational_number_dv = 1
545
+ node_2_1.save!
546
+ expect(node(:node_2_1).rational_number).to eq(RationalNumber.new(1,1))
547
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(2,1))
548
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(3,1))
549
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(4,1))
550
+ end
551
+
552
+ it "should move conflicting nodes and their children when setting position" do
553
+ node_2 = node(:node_2)
554
+ node_2.move_to_position(1)
555
+ node_2.save!
556
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(1,1))
557
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(2,1))
558
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(3,1))
559
+ end
560
+
561
+ it "should move conflicting nodes and their children when setting nv/dv trough function" do
562
+ node_2 = node(:node_2)
563
+ node_2.move_to_rational_number(1,1)
564
+ node_2.save!
565
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(1,1))
566
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(2,1))
567
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(3,1))
568
+ end
569
+ end
570
+
571
+ describe "#move_to_top" do
572
+ it "should return true when attempting to move the first sibling" do
573
+ expect(node(:node_1).move_to_top).to eq(true)
574
+ expect(node(:node_1_1).move_to_top).to eq(true)
575
+ end
576
+
577
+ it "should be able to move the last sibling to the top" do
578
+ first_node = node(:node_1)
579
+ last_node = node(:node_3)
580
+ last_node.move_to_top
581
+ first_node.reload
582
+ expect(last_node).to be_at_top
583
+ expect(first_node).not_to be_at_top
584
+ expect(first_node.higher_siblings.to_a).to eq([last_node])
585
+ expect(last_node.lower_siblings.to_a).to eq([first_node, node(:node_2)])
586
+
587
+ expect(first_node.rational_number).to eq(RationalNumber.new(2,1))
588
+ expect(last_node.rational_number).to eq(RationalNumber.new(1,1))
589
+ end
590
+
591
+ it 'should rekey the children of a node when moving the node' do
592
+ node_2_4_1_prev_keys = node(:node_2_4_1).rational_number
593
+ node_2_4_2_prev_keys = node(:node_2_4_2).rational_number
594
+ node_2 = node(:node_2)
595
+ node_2.move_to_top
596
+ node_2.reload
597
+ expect(node_2).to be_at_top
598
+
599
+ expect(node(:node_2_4_1).rational_number).not_to eq(node_2_4_1_prev_keys)
600
+ expect(node(:node_2_4_2).rational_number).not_to eq(node_2_4_2_prev_keys)
601
+ expect(node(:node_2_4_1).rational_number).to eq(RationalNumber.new(20,11))
602
+ expect(node(:node_2_4_2).rational_number).to eq(RationalNumber.new(31,17))
603
+ end
604
+
605
+ end
606
+
607
+ describe "#move_to_bottom" do
608
+ it "should return true when attempting to move the last sibling" do
609
+ expect(node(:node_3).move_to_bottom).to eq(true)
610
+ expect(node(:node_1_2).move_to_bottom).to eq(true)
611
+ end
612
+
613
+ it "should be able to move the first sibling to the bottom" do
614
+ first_node = node(:node_1)
615
+ middle_node = node(:node_2)
616
+ last_node = node(:node_3)
617
+ first_node.move_to_bottom
618
+ middle_node.reload
619
+ last_node.reload
620
+ expect(first_node).not_to be_at_top
621
+ expect(first_node).to be_at_bottom
622
+ expect(last_node).not_to be_at_bottom
623
+ expect(last_node).not_to be_at_top
624
+ expect(middle_node).to be_at_top
625
+ expect(first_node.lower_siblings.to_a).to eq([])
626
+ expect(last_node.higher_siblings.to_a).to eq([middle_node])
627
+
628
+ expect(middle_node.rational_number).to eq(RationalNumber.new(1,1))
629
+ expect(last_node.rational_number).to eq(RationalNumber.new(2,1))
630
+ expect(first_node.rational_number).to eq(RationalNumber.new(3,1))
631
+ end
632
+
633
+ it 'should rekey the children of a node when moving the node' do
634
+ node_2_4_1_prev_keys = node(:node_2_4_1).rational_number
635
+ node_2_4_2_prev_keys = node(:node_2_4_2).rational_number
636
+ node_2 = node(:node_2)
637
+ node_2.move_to_bottom
638
+ node_2.reload
639
+ expect(node_2).to be_at_bottom
640
+
641
+ expect(node(:node_2_4_1).rational_number).not_to eq(node_2_4_1_prev_keys)
642
+ expect(node(:node_2_4_2).rational_number).not_to eq(node_2_4_2_prev_keys)
643
+ expect(node(:node_2_4_1).rational_number).to eq(RationalNumber.new(42,11))
644
+ expect(node(:node_2_4_2).rational_number).to eq(RationalNumber.new(65,17))
645
+ end
646
+ end
647
+
648
+ describe "#move_up" do
649
+ it "should correctly move nodes up" do
650
+ node(:node_2_3).move_up
651
+ expect(node(:node_2).children).to eq([node(:node_2_1), node(:node_2_3), node(:node_2_2), node(:node_2_4)])
652
+ end
653
+ end
654
+
655
+ describe "#move_down" do
656
+ it "should correctly move nodes down" do
657
+ node(:node_2_3).move_down
658
+ expect(node(:node_2).children).to eq([node(:node_2_1), node(:node_2_2), node(:node_2_4), node(:node_2_3)])
659
+ end
660
+ end
661
+ end # moving nodes with small tree
662
+
663
+ describe "querying the tree" do
664
+ before(:each) do
665
+ setup_tree <<-ENDTREE
666
+ - node_1:
667
+ - node_1_1
668
+ - node_1_2:
669
+ - node_1_2_1:
670
+ - node_1_2_1_1
671
+ - node_1_2_1_2
672
+ - node_1_2_2:
673
+ - node_1_2_2_1
674
+ - node_2:
675
+ - node_2_1:
676
+ - node_2_1_1
677
+ - node_3:
678
+ - node_3_1
679
+ - node_3_2
680
+ ENDTREE
681
+ end
682
+ it "should get the tree under the given node" do
683
+ expect(node(:node_1).tree.all).to eq([node(:node_1_1), node(:node_1_2), node(:node_1_2_1), node(:node_1_2_1_1), node(:node_1_2_1_2), node(:node_1_2_2), node(:node_1_2_2_1)])
684
+ expect(node(:node_2).tree.all).to eq([node(:node_2_1), node(:node_2_1_1)])
685
+ expect(node(:node_3).tree.all).to eq([node(:node_3_1), node(:node_3_2)])
686
+
687
+ expect(node(:node_1).tree_and_self.all).to eq([node(:node_1), node(:node_1_1), node(:node_1_2), node(:node_1_2_1), node(:node_1_2_1_1), node(:node_1_2_1_2), node(:node_1_2_2), node(:node_1_2_2_1)])
688
+ expect(node(:node_2).tree_and_self.all).to eq([node(:node_2), node(:node_2_1), node(:node_2_1_1)])
689
+ expect(node(:node_3).tree_and_self.all).to eq([node(:node_3), node(:node_3_1), node(:node_3_2)])
690
+ end
691
+ end
692
+
693
+ describe "when rekeying" do
694
+ before(:each) do
695
+ setup_tree <<-ENDTREE
696
+ - node_1
697
+ - node_2:
698
+ - node_2_1
699
+ - node_2_2
700
+ - node_2_3
701
+ - node_2_4:
702
+ - node_2_4_1
703
+ - node_2_4_2
704
+ - node_2_4_3
705
+ - node_3
706
+ ENDTREE
707
+ end
708
+ it "should rekey the entire tree" do
709
+ # Force two gaps in the order
710
+ node_3 = node(:node_3)
711
+ node_3.move_to_position(8, {:force => true})
712
+ node_3.save_with_force_rational_numbers!
713
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(8,1))
714
+
715
+ node_2 = node(:node_2)
716
+ node_2.move_to_position(4, {:force => true})
717
+ node_2.save_with_force_rational_numbers!
718
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(4,1))
719
+
720
+ RationalNumberedNode.rekey_all!
721
+
722
+ # all nodes should still have their respective positions
723
+
724
+ expect(node(:node_1).rational_number).to eq(RationalNumber.new(1,1))
725
+ expect(node(:node_2).rational_number).to eq(RationalNumber.new(2,1))
726
+ expect(node(:node_3).rational_number).to eq(RationalNumber.new(3,1))
727
+ expect(node(:node_2_1).rational_number).to eq(RationalNumber.new(5,2))
728
+ expect(node(:node_2_2).rational_number).to eq(RationalNumber.new(8,3))
729
+ expect(node(:node_2_3).rational_number).to eq(RationalNumber.new(11,4))
730
+ expect(node(:node_2_4).rational_number).to eq(RationalNumber.new(14,5))
731
+ expect(node(:node_2_4_1).rational_number).to eq(RationalNumber.new(31,11))
732
+ expect(node(:node_2_4_2).rational_number).to eq(RationalNumber.new(48,17))
733
+ expect(node(:node_2_4_3).rational_number).to eq(RationalNumber.new(65,23))
734
+ end
735
+ end
736
+
737
+ describe "testing validations" do
738
+ before(:each) do
739
+ setup_tree <<-ENDTREE
740
+ - node_1
741
+ - node_2:
742
+ - node_2_1
743
+ - node_3
744
+ ENDTREE
745
+ end
746
+
747
+ it "should fail validation when trying to set invalid nv/dv (parent not found)" do
748
+ node_to_move = node(:node_2_1)
749
+ node_to_move.rational_number_nv = 65
750
+ node_to_move.rational_number_dv = 23
751
+ node_to_move.save
752
+ expect(node_to_move).not_to be_valid
753
+ end
754
+
755
+ it "should fail validation when trying to nv/dv resulting in cyclic relation" do
756
+ node_to_move = node(:node_2)
757
+ node_to_move.rational_number_nv = 13
758
+ node_to_move.rational_number_dv = 15
759
+ node_to_move.save
760
+ expect(node_to_move).not_to be_valid
761
+ end
762
+
763
+ end # describe "testing validations"
764
+
765
+ end # Mongoid::Tree::RationalNumbering