rambling-trie 0.8.1 → 0.9.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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/lib/rambling/trie.rb +21 -9
  4. data/lib/rambling/trie/compressed_node.rb +112 -0
  5. data/lib/rambling/trie/compression.rb +13 -0
  6. data/lib/rambling/trie/compressor.rb +30 -31
  7. data/lib/rambling/trie/{root.rb → container.rb} +41 -38
  8. data/lib/rambling/trie/enumerable.rb +11 -7
  9. data/lib/rambling/trie/missing_node.rb +1 -1
  10. data/lib/rambling/trie/node.rb +25 -22
  11. data/lib/rambling/trie/plain_text_reader.rb +1 -1
  12. data/lib/rambling/trie/raw_node.rb +90 -0
  13. data/lib/rambling/trie/tasks/helpers/path.rb +13 -0
  14. data/lib/rambling/trie/tasks/helpers/time.rb +7 -0
  15. data/lib/rambling/trie/tasks/performance.rb +10 -91
  16. data/lib/rambling/trie/tasks/performance/all.rb +4 -0
  17. data/lib/rambling/trie/tasks/performance/benchmark.rb +172 -0
  18. data/lib/rambling/trie/tasks/performance/directory.rb +11 -0
  19. data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +132 -0
  20. data/lib/rambling/trie/tasks/performance/profile/memory.rb +116 -0
  21. data/lib/rambling/trie/version.rb +1 -1
  22. data/rambling-trie.gemspec +6 -4
  23. data/spec/integration/rambling/trie_spec.rb +63 -9
  24. data/spec/lib/rambling/trie/compressed_node_spec.rb +35 -0
  25. data/spec/lib/rambling/trie/compressor_spec.rb +31 -0
  26. data/spec/lib/rambling/trie/container_spec.rb +470 -0
  27. data/spec/lib/rambling/trie/enumerable_spec.rb +2 -2
  28. data/spec/lib/rambling/trie/inspector_spec.rb +21 -14
  29. data/spec/lib/rambling/trie/node_spec.rb +72 -209
  30. data/spec/lib/rambling/trie/raw_node_spec.rb +377 -0
  31. data/spec/lib/rambling/trie_spec.rb +46 -25
  32. metadata +57 -16
  33. data/lib/rambling/trie/branches.rb +0 -149
  34. data/spec/lib/rambling/trie/branches_spec.rb +0 -52
  35. data/spec/lib/rambling/trie/root_spec.rb +0 -376
@@ -3,11 +3,11 @@ require 'spec_helper'
3
3
  module Rambling
4
4
  module Trie
5
5
  describe Enumerable do
6
- let(:root) { Root.new }
6
+ let(:root) { Rambling::Trie::RawNode.new }
7
7
  let(:words) { %w(add some words and another word) }
8
8
 
9
9
  before do
10
- words.each { |word| root << word.clone }
10
+ words.each { |word| root.add word.clone }
11
11
  end
12
12
 
13
13
  describe '#each' do
@@ -1,21 +1,28 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Rambling
4
- module Trie
5
- describe Inspector do
6
- let(:root) do
7
- Root.new do |trie|
8
- %w(only three words).each { |word| trie << word }
9
- end
10
- end
3
+ describe Rambling::Trie::Inspector do
4
+ let(:root) { Rambling::Trie::RawNode.new }
5
+
6
+ before do
7
+ %w(only three words).each { |word| root.add word }
8
+ end
9
+
10
+ describe '#inspect' do
11
+ let(:node) { root[:o] }
12
+
13
+ it 'returns a pretty printed version of the node' do
14
+ expect(root.inspect).to eq "#<Rambling::Trie::RawNode letter: nil, children: [:o, :t, :w]>"
15
+ expect(node.inspect).to eq "#<Rambling::Trie::RawNode letter: :o, children: [:n]>"
16
+ end
11
17
 
12
- let(:node) { root[:o] }
18
+ context 'for a compressed node' do
19
+ let(:compressor) { Rambling::Trie::Compressor.new }
20
+ let(:compressed_root) { compressor.compress root }
21
+ let(:compressed_node) { compressed_root[:only] }
13
22
 
14
- describe '#inspect' do
15
- it 'returns a pretty printed version of the node' do
16
- expect(root.inspect).to eq "#<Rambling::Trie::Root letter: nil, children: [:o, :t, :w]>"
17
- expect(node.inspect).to eq "#<Rambling::Trie::Node letter: :o, children: [:n]>"
18
- end
23
+ it 'returns a pretty printed version of the compressed node' do
24
+ expect(compressed_root.inspect).to eq "#<Rambling::Trie::CompressedNode letter: nil, children: [:only, :three, :words]>"
25
+ expect(compressed_node.inspect).to eq "#<Rambling::Trie::CompressedNode letter: :only, children: []>"
19
26
  end
20
27
  end
21
28
  end
@@ -1,228 +1,91 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Rambling
4
- module Trie
5
- describe Node do
6
- it 'delegates `#[]` to its children tree' do
7
- expect(subject.children_tree).to receive(:[]).with(:key).and_return('value')
8
- expect(subject[:key]).to eq 'value'
9
- end
3
+ describe Rambling::Trie::Node do
4
+ let(:node) { Rambling::Trie::Node.new }
10
5
 
11
- it 'delegates `#[]=` to its children tree' do
12
- expect(subject.children_tree).to receive(:[]=).with(:key, 'value')
13
- subject[:key] = 'value'
6
+ describe '#root?' do
7
+ context 'when the node has a parent' do
8
+ before do
9
+ node.parent = double :parent
14
10
  end
15
11
 
16
- it 'delegates `#delete` to its children tree' do
17
- expect(subject.children_tree).to receive(:delete).with(:key).and_return('value')
18
- expect(subject.delete :key).to eq 'value'
12
+ it 'returns false' do
13
+ expect(node).not_to be_root
19
14
  end
15
+ end
20
16
 
21
- it 'delegates `#has_key?` to its children tree' do
22
- expect(subject.children_tree).to receive(:has_key?).with(:present_key).and_return(true)
23
- expect(subject).to have_key(:present_key)
24
-
25
- expect(subject.children_tree).to receive(:has_key?).with(:absent_key).and_return(false)
26
- expect(subject).not_to have_key(:absent_key)
17
+ context 'when the node does not have a parent' do
18
+ before do
19
+ node.parent = nil
27
20
  end
28
21
 
29
- it 'delegates `#children` to its children tree values' do
30
- children = [double(:child_1), double(:child_2)]
31
- expect(subject.children_tree).to receive(:values).and_return(children)
32
- expect(subject.children).to eq children
22
+ it 'returns true' do
23
+ expect(node).to be_root
33
24
  end
25
+ end
26
+ end
34
27
 
35
- describe '#root?' do
36
- it 'returns false' do
37
- expect(subject).not_to be_root
38
- end
39
- end
28
+ describe '.new' do
29
+ let(:node) { Rambling::Trie::Node.new }
40
30
 
41
- describe '.new' do
42
- context 'with no word' do
43
- subject { Node.new }
31
+ it 'does not have any letter' do
32
+ expect(node.letter).to be_nil
33
+ end
44
34
 
45
- it 'does not have any letter' do
46
- expect(subject.letter).to be_nil
47
- end
35
+ it 'includes no children' do
36
+ expect(node.children.size).to eq 0
37
+ end
48
38
 
49
- it 'includes no children' do
50
- expect(subject.children.size).to eq 0
51
- end
52
-
53
- it 'is not a terminal node' do
54
- expect(subject).not_to be_terminal
55
- end
56
-
57
- it 'returns empty string as its word' do
58
- expect(subject.as_word).to be_empty
59
- end
60
-
61
- it 'is not compressed' do
62
- expect(subject).not_to be_compressed
63
- end
64
- end
65
-
66
- context 'with an empty word' do
67
- subject { Node.new '' }
68
-
69
- it 'does not have any letter' do
70
- expect(subject.letter).to be_nil
71
- end
72
-
73
- it 'includes no children' do
74
- expect(subject.children.size).to eq 0
75
- end
76
-
77
- it 'is not a terminal node' do
78
- expect(subject).not_to be_terminal
79
- end
80
-
81
- it 'returns empty string as its word' do
82
- expect(subject.as_word).to be_empty
83
- end
84
-
85
- it 'is not compressed' do
86
- expect(subject).not_to be_compressed
87
- end
88
- end
89
-
90
- context 'with one letter' do
91
- subject { Node.new 'a' }
92
-
93
- it 'makes it the node letter' do
94
- expect(subject.letter).to eq :a
95
- end
96
-
97
- it 'includes no children' do
98
- expect(subject.children.size).to eq 0
99
- end
100
-
101
- it 'is a terminal node' do
102
- expect(subject).to be_terminal
103
- end
104
- end
105
-
106
- context 'with two letters' do
107
- subject { Node.new 'ba' }
108
-
109
- it 'takes the first as the node letter' do
110
- expect(subject.letter).to eq :b
111
- end
112
-
113
- it 'includes one child' do
114
- expect(subject.children.size).to eq 1
115
- end
116
-
117
- it 'includes a child with the expected letter' do
118
- expect(subject.children.first.letter).to eq :a
119
- end
120
-
121
- it 'has the expected letter as a key' do
122
- expect(subject).to have_key(:a)
123
- end
124
-
125
- it 'returns the child corresponding to the key' do
126
- expect(subject[:a]).to eq subject.children_tree[:a]
127
- end
128
-
129
- it 'does not mark itself as a terminal node' do
130
- expect(subject).not_to be_terminal
131
- end
132
-
133
- it 'marks the first child as a terminal node' do
134
- expect(subject[:a]).to be_terminal
135
- end
136
- end
137
-
138
- context 'with a large word' do
139
- subject { Node.new 'spaghetti' }
140
-
141
- it 'marks the last letter as terminal node' do
142
- expect(subject[:p][:a][:g][:h][:e][:t][:t][:i]).to be_terminal
143
- end
144
-
145
- it 'does not mark any other letter as terminal node' do
146
- expect(subject[:p][:a][:g][:h][:e][:t][:t]).not_to be_terminal
147
- expect(subject[:p][:a][:g][:h][:e][:t]).not_to be_terminal
148
- expect(subject[:p][:a][:g][:h][:e]).not_to be_terminal
149
- expect(subject[:p][:a][:g][:h]).not_to be_terminal
150
- expect(subject[:p][:a][:g]).not_to be_terminal
151
- expect(subject[:p][:a]).not_to be_terminal
152
- expect(subject[:p]).not_to be_terminal
153
- end
154
- end
155
- end
39
+ it 'is not a terminal node' do
40
+ expect(node).not_to be_terminal
41
+ end
156
42
 
157
- describe '#as_word' do
158
- context 'for an empty node' do
159
- subject { Node.new '' }
160
-
161
- it 'returns nil' do
162
- expect(subject.as_word).to be_empty
163
- end
164
- end
165
-
166
- context 'for one letter' do
167
- subject { Node.new 'a' }
168
-
169
- it 'returns the expected one letter word' do
170
- expect(subject.as_word).to eq 'a'
171
- end
172
- end
173
-
174
- context 'for a small word' do
175
- subject { Node.new 'all' }
176
-
177
- it 'returns the expected small word' do
178
- expect(subject[:l][:l].as_word).to eq 'all'
179
- end
180
-
181
- it 'raises an error for a non terminal node' do
182
- expect { subject[:l].as_word }.to raise_error InvalidOperation
183
- end
184
- end
185
-
186
- context 'for a long word' do
187
- subject { Node.new 'beautiful' }
188
-
189
- it 'returns the expected long word' do
190
- expect(subject[:e][:a][:u][:t][:i][:f][:u][:l].as_word).to eq 'beautiful'
191
- end
192
- end
193
-
194
- context 'for a node with nil letter' do
195
- subject { Node.new nil }
196
- it 'returns nil' do
197
- expect(subject.as_word).to be_empty
198
- end
199
- end
200
- end
43
+ it 'returns empty string as its word' do
44
+ expect(node.as_word).to be_empty
45
+ end
46
+ end
201
47
 
202
- describe '#compressed?' do
203
- let(:root) { double :root }
204
- subject { Node.new '', root }
205
-
206
- context 'parent is compressed' do
207
- before do
208
- allow(root).to receive(:compressed?).and_return true
209
- end
210
-
211
- it 'returns true' do
212
- expect(subject).to be_compressed
213
- end
214
- end
215
-
216
- context 'parent is not compressed' do
217
- before do
218
- allow(root).to receive(:compressed?).and_return false
219
- end
220
-
221
- it 'returns false' do
222
- expect(subject).not_to be_compressed
223
- end
224
- end
225
- end
48
+ describe '#terminal!' do
49
+ it 'forces the node to be terminal' do
50
+ expect(node).not_to be_terminal
51
+ node.terminal!
52
+
53
+ expect(node).to be_terminal
54
+ end
55
+
56
+ it 'returns the node' do
57
+ expect(node.terminal!).to eq node
58
+ end
59
+ end
60
+
61
+ describe 'delegates and aliases' do
62
+ it 'delegates `#[]` to its children tree' do
63
+ expect(node.children_tree).to receive(:[]).with(:key).and_return('value')
64
+ expect(node[:key]).to eq 'value'
65
+ end
66
+
67
+ it 'delegates `#[]=` to its children tree' do
68
+ expect(node.children_tree).to receive(:[]=).with(:key, 'value')
69
+ node[:key] = 'value'
70
+ end
71
+
72
+ it 'delegates `#delete` to its children tree' do
73
+ expect(node.children_tree).to receive(:delete).with(:key).and_return('value')
74
+ expect(node.delete :key).to eq 'value'
75
+ end
76
+
77
+ it 'delegates `#has_key?` to its children tree' do
78
+ expect(node.children_tree).to receive(:has_key?).with(:present_key).and_return(true)
79
+ expect(node).to have_key(:present_key)
80
+
81
+ expect(node.children_tree).to receive(:has_key?).with(:absent_key).and_return(false)
82
+ expect(node).not_to have_key(:absent_key)
83
+ end
84
+
85
+ it 'delegates `#children` to its children tree values' do
86
+ children = [double(:child_1), double(:child_2)]
87
+ expect(node.children_tree).to receive(:values).and_return(children)
88
+ expect(node.children).to eq children
226
89
  end
227
90
  end
228
91
  end
@@ -0,0 +1,377 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rambling::Trie::RawNode do
4
+ let(:node) { Rambling::Trie::RawNode.new }
5
+
6
+ describe '#compressed?' do
7
+ it 'returns false' do
8
+ expect(node).not_to be_compressed
9
+ end
10
+ end
11
+
12
+ describe '.new' do
13
+ context 'with no word' do
14
+ let(:node) { Rambling::Trie::RawNode.new }
15
+
16
+ it 'does not have any letter' do
17
+ expect(node.letter).to be_nil
18
+ end
19
+
20
+ it 'includes no children' do
21
+ expect(node.children.size).to eq 0
22
+ end
23
+
24
+ it 'is not a terminal node' do
25
+ expect(node).not_to be_terminal
26
+ end
27
+
28
+ it 'returns empty string as its word' do
29
+ expect(node.as_word).to be_empty
30
+ end
31
+ end
32
+
33
+ describe '#letter=' do
34
+ let(:parent) { Rambling::Trie::RawNode.new }
35
+ let(:node) { Rambling::Trie::RawNode.new parent }
36
+
37
+ context 'with empty string' do
38
+ before do
39
+ node.letter = :a
40
+ node.add ''
41
+ end
42
+
43
+ it 'makes it the node letter' do
44
+ expect(node.letter).to eq :a
45
+ end
46
+
47
+ it 'includes no children' do
48
+ expect(node.children.size).to eq 0
49
+ end
50
+
51
+ it 'is a terminal node' do
52
+ expect(node).to be_terminal
53
+ end
54
+ end
55
+
56
+ context 'with one letter' do
57
+ before do
58
+ node.letter = :b
59
+ node.add 'a'
60
+ end
61
+
62
+ it 'takes the first as the node letter' do
63
+ expect(node.letter).to eq :b
64
+ end
65
+
66
+ it 'includes one child' do
67
+ expect(node.children.size).to eq 1
68
+ end
69
+
70
+ it 'includes a child with the expected letter' do
71
+ expect(node.children.first.letter).to eq :a
72
+ end
73
+
74
+ it 'has the expected letter as a key' do
75
+ expect(node).to have_key(:a)
76
+ end
77
+
78
+ it 'returns the child corresponding to the key' do
79
+ expect(node[:a]).to eq node.children_tree[:a]
80
+ end
81
+
82
+ it 'does not mark itself as a terminal node' do
83
+ expect(node).not_to be_terminal
84
+ end
85
+
86
+ it 'marks the first child as a terminal node' do
87
+ expect(node[:a]).to be_terminal
88
+ end
89
+ end
90
+
91
+ context 'with a large word' do
92
+ before do
93
+ node.letter = :s
94
+ node.add 'paghetti'
95
+ end
96
+
97
+ it 'marks the last letter as terminal node' do
98
+ expect(node[:p][:a][:g][:h][:e][:t][:t][:i]).to be_terminal
99
+ end
100
+
101
+ it 'does not mark any other letter as terminal node' do
102
+ expect(node[:p][:a][:g][:h][:e][:t][:t]).not_to be_terminal
103
+ expect(node[:p][:a][:g][:h][:e][:t]).not_to be_terminal
104
+ expect(node[:p][:a][:g][:h][:e]).not_to be_terminal
105
+ expect(node[:p][:a][:g][:h]).not_to be_terminal
106
+ expect(node[:p][:a][:g]).not_to be_terminal
107
+ expect(node[:p][:a]).not_to be_terminal
108
+ expect(node[:p]).not_to be_terminal
109
+ end
110
+ end
111
+
112
+ context 'with no parent' do
113
+ before do
114
+ node.letter = :a
115
+ node.add ''
116
+ end
117
+
118
+ it 'makes it the node letter' do
119
+ expect(node.letter).to eq :a
120
+ end
121
+
122
+ it 'includes no children' do
123
+ expect(node.children.size).to eq 0
124
+ end
125
+
126
+ it 'is a terminal node' do
127
+ expect(node).to be_terminal
128
+ end
129
+ end
130
+ end
131
+
132
+ context 'with no parent' do
133
+ let(:node) { Rambling::Trie::RawNode.new }
134
+
135
+ it 'is marked as root' do
136
+ expect(node).to be_root
137
+ end
138
+ end
139
+
140
+ context 'with a specified parent' do
141
+ let(:node) { Rambling::Trie::RawNode.new double(:root) }
142
+
143
+ it 'is not marked as root' do
144
+ expect(node).not_to be_root
145
+ end
146
+ end
147
+
148
+ it 'has no children' do
149
+ expect(node.children.size).to eq 0
150
+ end
151
+
152
+ it 'has no letter' do
153
+ expect(node.letter).to be_nil
154
+ end
155
+
156
+ it 'is not a terminal node' do
157
+ expect(node).not_to be_terminal
158
+ end
159
+
160
+ it 'is not a word' do
161
+ expect(node).not_to be_word
162
+ end
163
+ end
164
+
165
+ describe '#add' do
166
+ context 'when the node has no branches' do
167
+ before do
168
+ node.add 'abc'
169
+ end
170
+
171
+ it 'adds only one child' do
172
+ expect(node.children.size).to eq 1
173
+ end
174
+
175
+ it 'adds the full subtree' do
176
+ expect(node[:a]).not_to be_nil
177
+ expect(node[:a][:b]).not_to be_nil
178
+ expect(node[:a][:b][:c]).not_to be_nil
179
+ end
180
+
181
+ it 'marks only the last child as terminal' do
182
+ expect(node).not_to be_terminal
183
+ expect(node[:a]).not_to be_terminal
184
+ expect(node[:a][:b]).not_to be_terminal
185
+ expect(node[:a][:b][:c]).to be_terminal
186
+ end
187
+ end
188
+
189
+ context 'when the word being added already exists in the node' do
190
+ before do
191
+ node.add 'ack'
192
+ end
193
+
194
+ it 'does not increment any child count in the tree' do
195
+ node.add 'ack'
196
+
197
+ expect(node.children.size).to eq 1
198
+ expect(node[:a].children.size).to eq 1
199
+ expect(node[:a][:c].children.size).to eq 1
200
+ expect(node[:a][:c][:k].children.size).to eq 0
201
+ end
202
+
203
+ it 'does not mark any child as terminal in the tree' do
204
+ node.add 'ack'
205
+
206
+ expect(node).not_to be_terminal
207
+ expect(node[:a]).not_to be_terminal
208
+ expect(node[:a][:c]).not_to be_terminal
209
+ expect(node[:a][:c][:k]).to be_terminal
210
+ end
211
+
212
+ it 'returns the added node' do
213
+ expect(node.add('ack').letter).to eq :a
214
+ end
215
+ end
216
+
217
+ context 'when the word does not exist in the tree but the letters do' do
218
+ before do
219
+ node.add 'ack'
220
+ end
221
+
222
+ it 'does not add another branch' do
223
+ node.add 'a'
224
+ expect(node.children.size).to eq 1
225
+ end
226
+
227
+ it 'marks the corresponding node as terminal' do
228
+ node.add 'a'
229
+
230
+ expect(node).not_to be_terminal
231
+ expect(node[:a]).to be_terminal
232
+ expect(node[:a][:c]).not_to be_terminal
233
+ expect(node[:a][:c][:k]).to be_terminal
234
+ end
235
+
236
+ it 'returns the added node' do
237
+ expect(node.add('a').letter).to eq :a
238
+ end
239
+ end
240
+ end
241
+
242
+ describe '#partial_word?' do
243
+ context 'when the chars array is empty' do
244
+ it 'returns true' do
245
+ expect(node.partial_word? []).to be true
246
+ end
247
+ end
248
+
249
+ context 'when the chars array is not empty' do
250
+ context 'when the node has a tree that matches the characters' do
251
+ before do
252
+ node.add 'abc'
253
+ end
254
+
255
+ it 'returns true' do
256
+ expect(node.partial_word? %w(a)).to be true
257
+ expect(node.partial_word? %w(a b)).to be true
258
+ expect(node.partial_word? %w(a b c)).to be true
259
+ end
260
+ end
261
+
262
+ context 'when the node has a tree that does not match the characters' do
263
+ before do
264
+ node.add 'cba'
265
+ end
266
+
267
+ it 'returns false' do
268
+ expect(node.partial_word? %w(a)).to be false
269
+ expect(node.partial_word? %w(a b)).to be false
270
+ expect(node.partial_word? %w(a b c)).to be false
271
+ end
272
+ end
273
+ end
274
+ end
275
+
276
+ describe '#word?' do
277
+ context 'when the chars array is empty' do
278
+ context 'when the node is terminal' do
279
+ before do
280
+ node.terminal!
281
+ end
282
+
283
+ it 'returns true' do
284
+ expect(node.word? []).to be true
285
+ end
286
+ end
287
+
288
+ context 'when the node is not terminal' do
289
+ it 'returns false' do
290
+ expect(node.word? []).to be false
291
+ end
292
+ end
293
+ end
294
+
295
+ context 'when the chars array is not empty' do
296
+ context 'when the node has a tree that matches all the characters' do
297
+ before do
298
+ node.add 'abc'
299
+ end
300
+
301
+ it 'returns true' do
302
+ expect(node.word? %w(a b c)).to be true
303
+ end
304
+ end
305
+
306
+ context 'when the node has a tree that does not match all the characters' do
307
+ before do
308
+ node.add 'abc'
309
+ end
310
+
311
+ it 'returns false' do
312
+ expect(node.word? %w(a)).to be false
313
+ expect(node.word? %w(a b)).to be false
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ describe '#as_word' do
320
+ let(:node) { Rambling::Trie::RawNode.new }
321
+
322
+ context 'for an empty node' do
323
+ before do
324
+ node.add ''
325
+ end
326
+
327
+ it 'returns nil' do
328
+ expect(node.as_word).to be_empty
329
+ end
330
+ end
331
+
332
+ context 'for one letter' do
333
+ before do
334
+ node.letter = :a
335
+ node.add ''
336
+ end
337
+
338
+ it 'returns the expected one letter word' do
339
+ expect(node.as_word).to eq 'a'
340
+ end
341
+ end
342
+
343
+ context 'for a small word' do
344
+ before do
345
+ node.letter = :a
346
+ node.add 'll'
347
+ end
348
+
349
+ it 'returns the expected small word' do
350
+ expect(node[:l][:l].as_word).to eq 'all'
351
+ end
352
+
353
+ it 'raises an error for a non terminal node' do
354
+ expect { node[:l].as_word }.to raise_error Rambling::Trie::InvalidOperation
355
+ end
356
+ end
357
+
358
+ context 'for a long word' do
359
+ before do
360
+ node.letter = :b
361
+ node.add 'eautiful'
362
+ end
363
+
364
+ it 'returns the expected long word' do
365
+ expect(node[:e][:a][:u][:t][:i][:f][:u][:l].as_word).to eq 'beautiful'
366
+ end
367
+ end
368
+
369
+ context 'for a node with nil letter' do
370
+ let(:node) { Rambling::Trie::RawNode.new nil }
371
+
372
+ it 'returns nil' do
373
+ expect(node.as_word).to be_empty
374
+ end
375
+ end
376
+ end
377
+ end