rambling-trie 1.0.2 → 1.0.3

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/README.md +23 -7
  4. data/Rakefile +4 -0
  5. data/lib/rambling/trie.rb +27 -21
  6. data/lib/rambling/trie/comparable.rb +3 -3
  7. data/lib/rambling/trie/compressible.rb +14 -0
  8. data/lib/rambling/trie/compressor.rb +37 -24
  9. data/lib/rambling/trie/configuration/properties.rb +8 -6
  10. data/lib/rambling/trie/configuration/provider_collection.rb +34 -16
  11. data/lib/rambling/trie/container.rb +156 -36
  12. data/lib/rambling/trie/enumerable.rb +4 -4
  13. data/lib/rambling/trie/nodes.rb +11 -0
  14. data/lib/rambling/trie/nodes/compressed.rb +115 -0
  15. data/lib/rambling/trie/nodes/missing.rb +10 -0
  16. data/lib/rambling/trie/nodes/node.rb +151 -0
  17. data/lib/rambling/trie/nodes/raw.rb +89 -0
  18. data/lib/rambling/trie/readers/plain_text.rb +1 -11
  19. data/lib/rambling/trie/serializers/marshal.rb +4 -4
  20. data/lib/rambling/trie/serializers/yaml.rb +4 -4
  21. data/lib/rambling/trie/serializers/zip.rb +9 -8
  22. data/lib/rambling/trie/version.rb +1 -1
  23. data/spec/assets/test_words.es_DO.txt +1 -0
  24. data/spec/integration/rambling/trie_spec.rb +40 -35
  25. data/spec/lib/rambling/trie/comparable_spec.rb +6 -15
  26. data/spec/lib/rambling/trie/compressor_spec.rb +88 -13
  27. data/spec/lib/rambling/trie/configuration/properties_spec.rb +7 -7
  28. data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +8 -20
  29. data/spec/lib/rambling/trie/container_spec.rb +159 -168
  30. data/spec/lib/rambling/trie/enumerable_spec.rb +12 -9
  31. data/spec/lib/rambling/trie/inspectable_spec.rb +11 -11
  32. data/spec/lib/rambling/trie/nodes/compressed_spec.rb +35 -0
  33. data/spec/lib/rambling/trie/nodes/node_spec.rb +7 -0
  34. data/spec/lib/rambling/trie/nodes/raw_spec.rb +177 -0
  35. data/spec/lib/rambling/trie/serializers/file_spec.rb +4 -4
  36. data/spec/lib/rambling/trie/serializers/marshal_spec.rb +3 -7
  37. data/spec/lib/rambling/trie/serializers/yaml_spec.rb +3 -7
  38. data/spec/lib/rambling/trie/serializers/zip_spec.rb +16 -20
  39. data/spec/lib/rambling/trie/stringifyable_spec.rb +7 -8
  40. data/spec/lib/rambling/trie_spec.rb +2 -2
  41. data/spec/spec_helper.rb +3 -1
  42. data/spec/support/config.rb +4 -0
  43. data/spec/support/helpers/add_word.rb +18 -0
  44. data/spec/support/shared_examples/{a_compressable_trie.rb → a_compressible_trie.rb} +13 -3
  45. data/spec/support/shared_examples/a_serializable_trie.rb +8 -6
  46. data/spec/support/shared_examples/a_serializer.rb +6 -0
  47. data/spec/{lib/rambling/trie/node_spec.rb → support/shared_examples/a_trie_node.rb} +61 -30
  48. data/spec/{lib/rambling/trie/compressed_node_spec.rb → support/shared_examples/a_trie_node_implementation.rb} +18 -69
  49. metadata +22 -15
  50. data/lib/rambling/trie/compressable.rb +0 -14
  51. data/lib/rambling/trie/compressed_node.rb +0 -120
  52. data/lib/rambling/trie/missing_node.rb +0 -8
  53. data/lib/rambling/trie/node.rb +0 -97
  54. data/lib/rambling/trie/raw_node.rb +0 -96
  55. data/spec/lib/rambling/trie/raw_node_spec.rb +0 -389
@@ -1,14 +0,0 @@
1
- module Rambling
2
- module Trie
3
- # Provides the compressable behavior for the trie data structure.
4
- module Compressable
5
- # Indicates if the current {Rambling::Trie::Node Node} can be compressed
6
- # or not.
7
- # @return [Boolean] `true` for non-{Node#terminal? terminal} nodes with
8
- # one child, `false` otherwise.
9
- def compressable?
10
- !(root? || terminal?) && children_tree.size == 1
11
- end
12
- end
13
- end
14
- end
@@ -1,120 +0,0 @@
1
- module Rambling
2
- module Trie
3
- # A representation of a node in an compressed trie data structure.
4
- class CompressedNode < Rambling::Trie::Node
5
- # Always raises {Rambling::Trie::InvalidOperation InvalidOperation} when
6
- # trying to add a word to the current compressed trie node
7
- # @param [String] word the word to add to the trie.
8
- # @raise [InvalidOperation] if the trie is already compressed.
9
- # @return [nil] this never returns as it always raises an exception.
10
- def add word
11
- raise Rambling::Trie::InvalidOperation, 'Cannot add word to compressed trie'
12
- end
13
-
14
- # Checks if a path for set a of characters exists in the trie.
15
- # @param [Array<String>] chars the characters to look for in the trie.
16
- # @return [Boolean] `true` if the characters are found, `false` otherwise.
17
- def partial_word? chars
18
- chars.empty? || has_partial_word?(chars)
19
- end
20
-
21
- # Checks if a path for set of characters represents a word in the trie.
22
- # @param [Array<String>] chars the characters to look for in the trie.
23
- # @return [Boolean] `true` if the characters are found and form a word,
24
- # `false` otherwise.
25
- def word? chars
26
- chars.empty? ? terminal? : has_word?(chars)
27
- end
28
-
29
- # Returns the node that starts with the specified characters.
30
- # @param [Array<String>] chars the characters to look for in the trie.
31
- # @return [Node] the node that matches the specified characters.
32
- # {MissingNode MissingNode} when not found.
33
- def scan chars
34
- chars.empty? ? self : closest_node(chars)
35
- end
36
-
37
- # Always return `true` for a compressed node.
38
- # @return [Boolean] always `true` for a compressed node.
39
- def compressed?
40
- true
41
- end
42
-
43
- private
44
-
45
- def has_partial_word? chars
46
- recursive_get(:partial_word?, chars) || false
47
- end
48
-
49
- def has_word? chars
50
- current_key = nil
51
-
52
- while !chars.empty?
53
- if current_key
54
- current_key << chars.slice!(0)
55
- else
56
- current_key = chars.slice!(0)
57
- end
58
-
59
- child = children_tree[current_key.to_sym]
60
- return child.word? chars if child
61
- end
62
-
63
- false
64
- end
65
-
66
- def closest_node chars
67
- recursive_get(:scan, chars) || Rambling::Trie::MissingNode.new
68
- end
69
-
70
- def children_match_prefix chars
71
- return enum_for :children_match_prefix, chars unless block_given?
72
-
73
- current_key = nil
74
-
75
- while !chars.empty?
76
- if current_key
77
- current_key << chars.slice!(0)
78
- else
79
- current_key = chars.slice!(0)
80
- end
81
-
82
- child = children_tree[current_key.to_sym]
83
-
84
- if child
85
- child.match_prefix chars do |word|
86
- yield word
87
- end
88
- end
89
- end
90
- end
91
-
92
- def recursive_get method, chars
93
- current_length = 0
94
- current_key = current_key chars.slice!(0)
95
-
96
- begin
97
- current_length += 1
98
-
99
- if current_key && (current_key.length == current_length || chars.empty?)
100
- return children_tree[current_key.to_sym].send method, chars
101
- end
102
- end while current_key && current_key[current_length] == chars.slice!(0)
103
- end
104
-
105
- def current_key letter
106
- current_key = nil
107
-
108
- children_tree.keys.each do |key|
109
- key_string = key.to_s
110
- if key_string.start_with? letter
111
- current_key = key_string
112
- break
113
- end
114
- end
115
-
116
- current_key
117
- end
118
- end
119
- end
120
- end
@@ -1,8 +0,0 @@
1
- module Rambling
2
- module Trie
3
- # A representation of a missing node in the trie data structure. Returned
4
- # when a node is not found.
5
- class MissingNode < Rambling::Trie::Node
6
- end
7
- end
8
- end
@@ -1,97 +0,0 @@
1
- module Rambling
2
- module Trie
3
- # A representation of a node in the trie data structure.
4
- class Node
5
- extend ::Forwardable
6
- include Rambling::Trie::Compressable
7
- include Rambling::Trie::Enumerable
8
- include Rambling::Trie::Comparable
9
- include Rambling::Trie::Stringifyable
10
- include Rambling::Trie::Inspectable
11
-
12
- delegate [
13
- :[],
14
- :[]=,
15
- :delete,
16
- :has_key?
17
- ] => :children_tree
18
-
19
- # @overload letter
20
- # Letter(s) corresponding to the current node.
21
- # @overload letter=(letter)
22
- # Sets the letter(s) corresponding to the current node. Ensures the
23
- # {Node#letter #letter} in the {Node#parent #parent}'s
24
- # {Node#children_tree #children_tree} is updated.
25
- # @param [String, Symbol, nil] letter the new letter value.
26
- # @return [Symbol, nil] the corresponding letter(s).
27
- attr_reader :letter
28
-
29
- # Children nodes tree.
30
- # @return [Hash] the children_tree hash, consisting of `:letter => node`.
31
- attr_accessor :children_tree
32
-
33
- # Parent node.
34
- # @return [Node, nil] the parent of the current node.
35
- attr_accessor :parent
36
-
37
- # Creates a new node.
38
- # @param [Node, nil] parent the parent of the current node.
39
- def initialize parent = nil
40
- self.parent = parent
41
- self.children_tree = {}
42
- end
43
-
44
- # Children nodes.
45
- # @return [Array<Node>] the array of children nodes contained in the
46
- # current node.
47
- def children
48
- children_tree.values
49
- end
50
-
51
- # Indicates if the current node is the root node.
52
- # @return [Boolean] `true` if the node does not have a parent, `false`
53
- # otherwise.
54
- def root?
55
- !parent
56
- end
57
-
58
- # Indicates if a {Node Node} is terminal or not.
59
- # @return [Boolean] `true` for terminal nodes, `false` otherwise.
60
- def terminal?
61
- !!terminal
62
- end
63
-
64
- # Mark {Node Node} as terminal.
65
- # @return [Node] the modified node.
66
- def terminal!
67
- self.terminal = true
68
- self
69
- end
70
-
71
- def letter= letter
72
- if letter
73
- @letter = letter.to_sym
74
- parent[letter] = self if parent
75
- end
76
- end
77
-
78
- # Returns all words that match a prefix of any length within chars.
79
- # @param [String] chars the chars to base the prefix on.
80
- # @return [Enumerator<String>] all the words that match a prefix given by
81
- # chars.
82
- # @yield [String] each word found.
83
- def match_prefix chars
84
- return enum_for :match_prefix, chars unless block_given?
85
-
86
- yield as_word if terminal?
87
- children_match_prefix chars do |word|
88
- yield word
89
- end
90
- end
91
-
92
- private
93
-
94
- attr_accessor :terminal
95
- end
96
- end
97
- end
@@ -1,96 +0,0 @@
1
- module Rambling
2
- module Trie
3
- # A representation of a node in an uncompressed trie data structure.
4
- class RawNode < Rambling::Trie::Node
5
- # Adds a word to the current raw (uncompressed) trie node.
6
- # @param [String] word the word to add to the trie.
7
- # @return [RawNode] the added/modified node based on the word added.
8
- # @note This method clears the contents of the word variable.
9
- def add word
10
- if word.empty?
11
- terminal!
12
- else
13
- add_to_children_tree word
14
- end
15
- end
16
-
17
- # Checks if a path for a set of characters exists in the trie.
18
- # @param [Array<String>] chars the characters to look for in the trie.
19
- # @return [Boolean] `true` if the characters are found, `false`
20
- # otherwise.
21
- def partial_word? chars = []
22
- if chars.empty?
23
- true
24
- else
25
- letter = chars.slice!(0).to_sym
26
- child = children_tree[letter]
27
- !!child && child.partial_word?(chars)
28
- end
29
- end
30
-
31
- # Checks if a path for set of characters represents a word in the trie.
32
- # @param [Array<String>] chars the characters to look for in the trie.
33
- # @return [Boolean] `true` if the characters are found and form a word,
34
- # `false` otherwise.
35
- def word? chars = []
36
- if chars.empty?
37
- terminal?
38
- else
39
- letter = chars.slice!(0).to_sym
40
- child = children_tree[letter]
41
- !!child && child.word?(chars)
42
- end
43
- end
44
-
45
- # Returns the node that starts with the specified characters.
46
- # @param [Array<String>] chars the characters to look for in the trie.
47
- # @return [Node] the node that matches the specified characters.
48
- # {MissingNode MissingNode} when not found.
49
- def scan chars
50
- chars.empty? ? self : closest_node(chars)
51
- end
52
-
53
- # Always return `false` for a raw (uncompressed) node.
54
- # @return [Boolean] always `false` for a raw (uncompressed) node.
55
- def compressed?
56
- false
57
- end
58
-
59
- private
60
-
61
- def add_to_children_tree word
62
- letter = word.slice!(0).to_sym
63
- child = children_tree[letter] || new_node(letter)
64
- child.add word
65
- child
66
- end
67
-
68
- def new_node letter
69
- node = Rambling::Trie::RawNode.new self
70
- node.letter = letter
71
- children_tree[letter] = node
72
- end
73
-
74
- def closest_node chars
75
- letter = chars.slice!(0).to_sym
76
- child = children_tree[letter]
77
-
78
- child ? child.scan(chars) : Rambling::Trie::MissingNode.new
79
- end
80
-
81
- def children_match_prefix chars
82
- return enum_for :children_match_prefix, chars unless block_given?
83
-
84
- if !chars.empty?
85
- letter = chars.slice!(0).to_sym
86
- child = children_tree[letter]
87
- if child
88
- child.match_prefix chars do |word|
89
- yield word
90
- end
91
- end
92
- end
93
- end
94
- end
95
- end
96
- end
@@ -1,389 +0,0 @@
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 '#scan' do
320
- context 'when the chars array is empty' do
321
- it 'returns itself' do
322
- expect(node.scan []).to eq node
323
- end
324
- end
325
-
326
- context 'when the chars array is not empty' do
327
- before do
328
- node.add 'cba'
329
- end
330
-
331
- context 'when the chars are found' do
332
- it 'returns the found child' do
333
- expect(node.scan %w(c)).to eq node[:c]
334
- expect(node.scan %w(c b)).to eq node[:c][:b]
335
- expect(node.scan %w(c b a)).to eq node[:c][:b][:a]
336
- end
337
- end
338
-
339
- context 'when the chars are not found' do
340
- it 'returns a MissingNode' do
341
- expect(node.scan %w(a)).to be_a Rambling::Trie::MissingNode
342
- expect(node.scan %w(a b)).to be_a Rambling::Trie::MissingNode
343
- expect(node.scan %w(a b c)).to be_a Rambling::Trie::MissingNode
344
- expect(node.scan %w(c b a d)).to be_a Rambling::Trie::MissingNode
345
- end
346
- end
347
- end
348
- end
349
-
350
- describe '#match_prefix' do
351
- before do
352
- node.letter = :i
353
- node.add 'gnite'
354
- node.add 'mport'
355
- node.add 'mportant'
356
- node.add 'mportantly'
357
- end
358
-
359
- context 'when the node is terminal' do
360
- before do
361
- node.terminal!
362
- end
363
-
364
- it 'adds itself to the words' do
365
- expect(node.match_prefix %w(g n i t e)).to include 'i'
366
- end
367
- end
368
-
369
- context 'when the node is not terminal' do
370
- it 'does not add itself to the words' do
371
- expect(node.match_prefix %w(g n i t e)).not_to include 'i'
372
- end
373
- end
374
-
375
- context 'when the first few chars match a terminal node' do
376
- it 'adds those terminal nodes to the words' do
377
- words = node.match_prefix(%w(m p o r t a n t l y)).to_a
378
- expect(words).to include 'import', 'important', 'importantly'
379
- end
380
- end
381
-
382
- context 'when the first few chars do not match a terminal node' do
383
- it 'does not add any other words found' do
384
- words = node.match_prefix(%w(m p m p o r t a n t l y)).to_a
385
- expect(words).not_to include 'import', 'important', 'importantly'
386
- end
387
- end
388
- end
389
- end