mongoid-tree-rational 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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