rambling-trie 2.3.0 → 2.4.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -0
  3. data/LICENSE +1 -1
  4. data/README.md +68 -29
  5. data/lib/rambling/trie/comparable.rb +2 -3
  6. data/lib/rambling/trie/compressible.rb +3 -5
  7. data/lib/rambling/trie/compressor.rb +2 -12
  8. data/lib/rambling/trie/configuration/properties.rb +8 -14
  9. data/lib/rambling/trie/configuration/provider_collection.rb +19 -27
  10. data/lib/rambling/trie/container.rb +28 -42
  11. data/lib/rambling/trie/enumerable.rb +4 -2
  12. data/lib/rambling/trie/nodes/compressed.rb +4 -5
  13. data/lib/rambling/trie/nodes/missing.rb +1 -2
  14. data/lib/rambling/trie/nodes/node.rb +21 -34
  15. data/lib/rambling/trie/nodes/raw.rb +2 -2
  16. data/lib/rambling/trie/readers/plain_text.rb +10 -6
  17. data/lib/rambling/trie/readers/reader.rb +19 -0
  18. data/lib/rambling/trie/readers.rb +1 -1
  19. data/lib/rambling/trie/serializers/file.rb +1 -1
  20. data/lib/rambling/trie/serializers/marshal.rb +12 -20
  21. data/lib/rambling/trie/serializers/serializer.rb +27 -0
  22. data/lib/rambling/trie/serializers/yaml.rb +10 -16
  23. data/lib/rambling/trie/serializers/zip.rb +9 -5
  24. data/lib/rambling/trie/serializers.rb +1 -1
  25. data/lib/rambling/trie/stringifyable.rb +1 -1
  26. data/lib/rambling/trie/version.rb +1 -1
  27. data/lib/rambling/trie.rb +19 -22
  28. data/rambling-trie.gemspec +9 -5
  29. data/spec/integration/rambling/trie_spec.rb +49 -20
  30. data/spec/lib/rambling/trie/comparable_spec.rb +29 -39
  31. data/spec/lib/rambling/trie/compressor_spec.rb +17 -14
  32. data/spec/lib/rambling/trie/configuration/properties_spec.rb +25 -7
  33. data/spec/lib/rambling/trie/configuration/provider_collection_spec.rb +44 -16
  34. data/spec/lib/rambling/trie/container_spec.rb +202 -327
  35. data/spec/lib/rambling/trie/enumerable_spec.rb +18 -10
  36. data/spec/lib/rambling/trie/inspectable_spec.rb +9 -3
  37. data/spec/lib/rambling/trie/nodes/compressed_spec.rb +6 -0
  38. data/spec/lib/rambling/trie/nodes/node_spec.rb +1 -1
  39. data/spec/lib/rambling/trie/nodes/raw_spec.rb +32 -27
  40. data/spec/lib/rambling/trie/readers/plain_text_spec.rb +11 -1
  41. data/spec/lib/rambling/trie/readers/reader_spec.rb +14 -0
  42. data/spec/lib/rambling/trie/serializers/file_spec.rb +2 -4
  43. data/spec/lib/rambling/trie/serializers/marshal_spec.rb +2 -4
  44. data/spec/lib/rambling/trie/serializers/serializer_spec.rb +21 -0
  45. data/spec/lib/rambling/trie/serializers/yaml_spec.rb +2 -4
  46. data/spec/lib/rambling/trie/serializers/zip_spec.rb +24 -16
  47. data/spec/lib/rambling/trie/stringifyable_spec.rb +17 -13
  48. data/spec/lib/rambling/trie_spec.rb +107 -45
  49. data/spec/spec_helper.rb +16 -9
  50. data/spec/support/shared_examples/a_compressible_trie.rb +9 -3
  51. data/spec/support/shared_examples/a_container_partial_word.rb +17 -0
  52. data/spec/support/shared_examples/a_container_scan.rb +14 -0
  53. data/spec/support/shared_examples/a_container_word.rb +43 -0
  54. data/spec/support/shared_examples/a_container_words_within.rb +44 -0
  55. data/spec/support/shared_examples/a_serializable_trie.rb +5 -9
  56. data/spec/support/shared_examples/a_serializer.rb +37 -14
  57. data/spec/support/shared_examples/a_trie_data_structure.rb +24 -10
  58. data/spec/support/shared_examples/a_trie_node.rb +22 -14
  59. data/spec/support/shared_examples/a_trie_node_implementation.rb +40 -43
  60. metadata +25 -9
@@ -8,21 +8,23 @@ module Rambling
8
8
  let(:node) { Rambling::Trie::Nodes::Raw.new }
9
9
  let(:words) { %w(add some words and another word) }
10
10
 
11
- before do
12
- add_words node, words
13
- end
11
+ before { add_words node, words }
14
12
 
15
13
  describe '#each' do
16
- it 'returns an enumerator' do
17
- expect(node.each).to be_a Enumerator
14
+ it 'returns an enumerator when no block is given' do
15
+ expect(node.each).to be_an Enumerator
16
+ end
17
+
18
+ it 'has the same word count as the trie' do
19
+ expect(node.count).to eq words.count
18
20
  end
19
21
 
20
22
  it 'includes every word contained in the trie' do
21
- node.each do |word|
22
- expect(words).to include word
23
- end
23
+ node.each { |word| expect(words).to include word }
24
+ end
24
25
 
25
- expect(node.count).to eq words.count
26
+ it 'returns the enumerable when a block is given' do
27
+ expect(node.each { |_| }).to eq node
26
28
  end
27
29
  end
28
30
 
@@ -32,9 +34,15 @@ module Rambling
32
34
  end
33
35
  end
34
36
 
35
- it 'includes the core Enumerable module' do
37
+ it 'includes #all? from the core Enumerable module' do
36
38
  expect(node.all? { |word| words.include? word }).to be true
39
+ end
40
+
41
+ it 'includes #any? from the core Enumerable module' do
37
42
  expect(node.any? { |word| word.start_with? 's' }).to be true
43
+ end
44
+
45
+ it 'includes #to_a from the core Enumerable module' do
38
46
  expect(node.to_a).to match_array words
39
47
  end
40
48
  end
@@ -13,19 +13,23 @@ describe Rambling::Trie::Inspectable do
13
13
  let(:child) { node[:o] }
14
14
  let(:terminal_node) { node[:o][:n][:l][:y] }
15
15
 
16
- it 'returns a pretty printed version of the node' do
16
+ it 'returns a pretty printed version of the parent node' do
17
17
  expect(node.inspect).to eq one_line <<~RAW
18
18
  #<Rambling::Trie::Nodes::Raw letter: nil,
19
19
  terminal: nil,
20
20
  children: [:o, :t, :w]>
21
21
  RAW
22
+ end
22
23
 
24
+ it 'returns a pretty printed version of the child node' do
23
25
  expect(child.inspect).to eq one_line <<~CHILD
24
26
  #<Rambling::Trie::Nodes::Raw letter: :o,
25
27
  terminal: nil,
26
28
  children: [:n]>
27
29
  CHILD
30
+ end
28
31
 
32
+ it 'returns a pretty printed version of the terminal node' do
29
33
  expect(terminal_node.inspect).to eq one_line <<~TERMINAL
30
34
  #<Rambling::Trie::Nodes::Raw letter: :y,
31
35
  terminal: true,
@@ -33,18 +37,20 @@ describe Rambling::Trie::Inspectable do
33
37
  TERMINAL
34
38
  end
35
39
 
36
- context 'for a compressed node' do
40
+ context 'with a compressed node' do
37
41
  let(:compressor) { Rambling::Trie::Compressor.new }
38
42
  let(:compressed) { compressor.compress node }
39
43
  let(:compressed_child) { compressed[:o] }
40
44
 
41
- it 'returns a pretty printed version of the compressed node' do
45
+ it 'returns a pretty printed version of the compressed parent node' do
42
46
  expect(compressed.inspect).to eq one_line <<~COMPRESSED
43
47
  #<Rambling::Trie::Nodes::Compressed letter: nil,
44
48
  terminal: nil,
45
49
  children: [:o, :t, :w]>
46
50
  COMPRESSED
51
+ end
47
52
 
53
+ it 'returns a pretty printed version of the compressed child node' do
48
54
  expect(compressed_child.inspect).to eq one_line <<~CHILD
49
55
  #<Rambling::Trie::Nodes::Compressed letter: :only,
50
56
  terminal: true,
@@ -7,6 +7,12 @@ describe Rambling::Trie::Nodes::Compressed do
7
7
  let(:compressor) { Rambling::Trie::Compressor.new }
8
8
  let(:node) { compressor.compress raw_node }
9
9
 
10
+ describe '#new' do
11
+ it 'is not a word' do
12
+ expect(node).not_to be_word
13
+ end
14
+ end
15
+
10
16
  it_behaves_like 'a trie node implementation' do
11
17
  def add_word_to_tree word
12
18
  add_word raw_node, word
@@ -4,6 +4,6 @@ require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Nodes::Node do
6
6
  it_behaves_like 'a trie node' do
7
- let(:node) { Rambling::Trie::Nodes::Node.new }
7
+ let(:node) { described_class.new }
8
8
  end
9
9
  end
@@ -3,7 +3,13 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Nodes::Raw do
6
- let(:node) { Rambling::Trie::Nodes::Raw.new }
6
+ let(:node) { described_class.new }
7
+
8
+ describe '#new' do
9
+ it 'is not a word' do
10
+ expect(node).not_to be_word
11
+ end
12
+ end
7
13
 
8
14
  it_behaves_like 'a trie node implementation' do
9
15
  def add_word_to_tree word
@@ -17,10 +23,6 @@ describe Rambling::Trie::Nodes::Raw do
17
23
  def assign_letter letter
18
24
  node.letter = letter
19
25
  end
20
-
21
- it 'is not a word' do
22
- expect(node).not_to be_word
23
- end
24
26
  end
25
27
 
26
28
  describe '#compressed?' do
@@ -31,26 +33,28 @@ describe Rambling::Trie::Nodes::Raw do
31
33
 
32
34
  describe '#add' do
33
35
  context 'when the node has no branches' do
34
- before do
35
- add_word node, 'abc'
36
- end
36
+ before { add_word node, 'abc' }
37
37
 
38
38
  it 'adds only one child' do
39
39
  expect(node.children.size).to eq 1
40
40
  end
41
41
 
42
+ # rubocop:disable RSpec/MultipleExpectations
42
43
  it 'adds the full subtree' do
43
44
  expect(node[:a]).not_to be_nil
44
45
  expect(node[:a][:b]).not_to be_nil
45
46
  expect(node[:a][:b][:c]).not_to be_nil
46
47
  end
48
+ # rubocop:enable RSpec/MultipleExpectations
47
49
 
50
+ # rubocop:disable RSpec/MultipleExpectations
48
51
  it 'marks only the last child as terminal' do
49
52
  expect(node).not_to be_terminal
50
53
  expect(node[:a]).not_to be_terminal
51
54
  expect(node[:a][:b]).not_to be_terminal
52
55
  expect(node[:a][:b][:c]).to be_terminal
53
56
  end
57
+ # rubocop:enable RSpec/MultipleExpectations
54
58
  end
55
59
 
56
60
  context 'when a word is added more than once' do
@@ -59,19 +63,23 @@ describe Rambling::Trie::Nodes::Raw do
59
63
  add_word node, 'ack'
60
64
  end
61
65
 
66
+ # rubocop:disable RSpec/MultipleExpectations
62
67
  it 'only counts it once' do
63
68
  expect(node.children.size).to eq 1
64
69
  expect(node[:a].children.size).to eq 1
65
70
  expect(node[:a][:c].children.size).to eq 1
66
71
  expect(node[:a][:c][:k].children.size).to eq 0
67
72
  end
73
+ # rubocop:enable RSpec/MultipleExpectations
68
74
 
75
+ # rubocop:disable RSpec/MultipleExpectations
69
76
  it 'does not change the terminal nodes in the tree' do
70
77
  expect(node).not_to be_terminal
71
78
  expect(node[:a]).not_to be_terminal
72
79
  expect(node[:a][:c]).not_to be_terminal
73
80
  expect(node[:a][:c][:k]).to be_terminal
74
81
  end
82
+ # rubocop:enable RSpec/MultipleExpectations
75
83
 
76
84
  it 'still returns the "added" node' do
77
85
  child = add_word node, 'ack'
@@ -80,21 +88,20 @@ describe Rambling::Trie::Nodes::Raw do
80
88
  end
81
89
 
82
90
  context 'when the word does not exist in the tree but the letters do' do
83
- before do
84
- add_words node, %w(ack a)
85
- end
91
+ before { add_words node, %w(ack a) }
86
92
 
87
93
  it 'does not add another branch' do
88
94
  expect(node.children.size).to eq 1
89
95
  end
90
96
 
97
+ # rubocop:disable RSpec/MultipleExpectations
91
98
  it 'marks the corresponding node as terminal' do
92
- expect(node[:a]).to be_terminal
93
-
94
99
  expect(node).not_to be_terminal
100
+ expect(node[:a]).to be_terminal
95
101
  expect(node[:a][:c]).not_to be_terminal
96
102
  expect(node[:a][:c][:k]).to be_terminal
97
103
  end
104
+ # rubocop:enable RSpec/MultipleExpectations
98
105
 
99
106
  it 'returns the added node' do
100
107
  child = add_word node, 'a'
@@ -103,13 +110,11 @@ describe Rambling::Trie::Nodes::Raw do
103
110
  end
104
111
 
105
112
  context 'when the node has a letter and a parent' do
106
- let(:parent) { Rambling::Trie::Nodes::Raw.new }
107
- let(:node) { Rambling::Trie::Nodes::Raw.new :a, parent }
113
+ let(:parent) { described_class.new }
114
+ let(:node) { described_class.new :a, parent }
108
115
 
109
- context 'adding an empty string' do
110
- before do
111
- add_word node, ''
112
- end
116
+ context 'when adding an empty string' do
117
+ before { add_word node, '' }
113
118
 
114
119
  it 'does not alter the node letter' do
115
120
  expect(node.letter).to eq :a
@@ -124,19 +129,19 @@ describe Rambling::Trie::Nodes::Raw do
124
129
  end
125
130
  end
126
131
 
127
- context 'adding a one letter word' do
128
- before do
129
- add_word node, 'b'
130
- end
132
+ context 'when adding a one letter word' do
133
+ before { add_word node, 'b' }
131
134
 
132
135
  it 'does not alter the node letter' do
133
136
  expect(node.letter).to eq :a
134
137
  end
135
138
 
139
+ # rubocop:disable RSpec/MultipleExpectations
136
140
  it 'adds a child with the expected letter' do
137
141
  expect(node.children.size).to eq 1
138
142
  expect(node.children.first.letter).to eq :b
139
143
  end
144
+ # rubocop:enable RSpec/MultipleExpectations
140
145
 
141
146
  it 'reports it has the expected letter a key' do
142
147
  expect(node).to have_key(:b)
@@ -155,15 +160,14 @@ describe Rambling::Trie::Nodes::Raw do
155
160
  end
156
161
  end
157
162
 
158
- context 'adding a large word' do
159
- before do
160
- add_word node, 'mplified'
161
- end
163
+ context 'when adding a large word' do
164
+ before { add_word node, 'mplified' }
162
165
 
163
166
  it 'marks the last letter as terminal' do
164
167
  expect(node[:m][:p][:l][:i][:f][:i][:e][:d]).to be_terminal
165
168
  end
166
169
 
170
+ # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations
167
171
  it 'does not mark any other letter as terminal' do
168
172
  expect(node[:m][:p][:l][:i][:f][:i][:e]).not_to be_terminal
169
173
  expect(node[:m][:p][:l][:i][:f][:i]).not_to be_terminal
@@ -173,6 +177,7 @@ describe Rambling::Trie::Nodes::Raw do
173
177
  expect(node[:m][:p]).not_to be_terminal
174
178
  expect(node[:m]).not_to be_terminal
175
179
  end
180
+ # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations
176
181
  end
177
182
  end
178
183
  end
@@ -3,14 +3,24 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Readers::PlainText do
6
+ subject(:reader) { described_class.new }
7
+
6
8
  describe '#each_word' do
7
9
  let(:filepath) { File.join(::SPEC_ROOT, 'assets', 'test_words.en_US.txt') }
8
10
  let(:words) { File.readlines(filepath).map(&:chomp) }
9
11
 
10
12
  it 'yields every word yielded by the file' do
11
13
  yielded = []
12
- subject.each_word(filepath) { |word| yielded << word }
14
+ reader.each_word(filepath) { |word| yielded << word }
13
15
  expect(yielded).to eq words
14
16
  end
17
+
18
+ it 'returns an enumerator when no block is given' do
19
+ expect(reader.each_word filepath).to be_an Enumerator
20
+ end
21
+
22
+ it 'returns the enumerable when a block is given' do
23
+ expect(reader.each_word(filepath) { |_| }).to eq reader
24
+ end
15
25
  end
16
26
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Rambling::Trie::Readers::Reader do
6
+ subject(:reader) { described_class.new }
7
+
8
+ describe '#load' do
9
+ it 'is an abstract method that raises NotImplementedError' do
10
+ expect { reader.each_word('any-file.zip') }
11
+ .to raise_exception NotImplementedError
12
+ end
13
+ end
14
+ end
@@ -4,10 +4,8 @@ require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Serializers::File do
6
6
  it_behaves_like 'a serializer' do
7
- let(:serializer) { Rambling::Trie::Serializers::File.new }
8
- let(:format) { :file }
9
-
7
+ let(:file_format) { :file }
10
8
  let(:content) { trie.to_a.join ' ' }
11
- let(:formatted_content) { content }
9
+ let(:format_content) { ->(content) { content } }
12
10
  end
13
11
  end
@@ -4,9 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Serializers::Marshal do
6
6
  it_behaves_like 'a serializer' do
7
- let(:serializer) { Rambling::Trie::Serializers::Marshal.new }
8
- let(:format) { :marshal }
9
-
10
- let(:formatted_content) { Marshal.dump content }
7
+ let(:file_format) { :marshal }
8
+ let(:format_content) { Marshal.method(:dump) }
11
9
  end
12
10
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Rambling::Trie::Serializers::Serializer do
6
+ subject(:serializer) { described_class.new }
7
+
8
+ describe '#load' do
9
+ it 'is an abstract method that raises NotImplementedError' do
10
+ expect { serializer.load('any-file.zip') }
11
+ .to raise_exception NotImplementedError
12
+ end
13
+ end
14
+
15
+ describe '#dump' do
16
+ it 'is an abstract method that raises NotImplementedError' do
17
+ expect { serializer.dump('any contents', 'any-file.zip') }
18
+ .to raise_exception NotImplementedError
19
+ end
20
+ end
21
+ end
@@ -4,9 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Serializers::Yaml do
6
6
  it_behaves_like 'a serializer' do
7
- let(:serializer) { Rambling::Trie::Serializers::Yaml.new }
8
- let(:format) { :yml }
9
-
10
- let(:formatted_content) { YAML.dump content }
7
+ let(:file_format) { :yml }
8
+ let(:format_content) { YAML.method(:dump) }
11
9
  end
12
10
  end
@@ -3,26 +3,34 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe Rambling::Trie::Serializers::Zip do
6
- it_behaves_like 'a serializer' do
7
- let(:properties) { Rambling::Trie::Configuration::Properties.new }
8
- let(:serializer) { Rambling::Trie::Serializers::Zip.new properties }
9
- let(:format) { 'marshal.zip' }
6
+ {
7
+ yaml: YAML.method(:dump),
8
+ yml: YAML.method(:dump),
9
+ marshal: Marshal.method(:dump),
10
+ file: Marshal.method(:dump),
11
+ }.each do |file_format, dump_method|
12
+ context "with '.#{file_format}'" do
13
+ it_behaves_like 'a serializer' do
14
+ let(:properties) { Rambling::Trie::Configuration::Properties.new }
15
+ let(:serializer) { described_class.new properties }
16
+ let(:file_format) { :zip }
10
17
 
11
- before do
12
- properties.tmp_path = tmp_path
13
- end
14
-
15
- let(:filename) { File.basename(filepath).gsub %r{\.zip}, '' }
16
- let(:formatted_content) { zip Marshal.dump content }
18
+ let(:filepath) { File.join tmp_path, "trie-root.#{file_format}.zip" }
19
+ let(:format_content) { ->(content) { zip dump_method.call content } }
20
+ let(:filename) { File.basename(filepath).gsub %r{\.zip}, '' }
17
21
 
18
- def zip content
19
- cursor = Zip::OutputStream.write_buffer do |io|
20
- io.put_next_entry filename
21
- io.write content
22
+ before { properties.tmp_path = tmp_path }
22
23
  end
24
+ end
25
+ end
23
26
 
24
- cursor.rewind
25
- cursor.read
27
+ def zip content
28
+ cursor = Zip::OutputStream.write_buffer do |io|
29
+ io.put_next_entry filename
30
+ io.write content
26
31
  end
32
+
33
+ cursor.rewind
34
+ cursor.read
27
35
  end
28
36
  end
@@ -6,17 +6,15 @@ describe Rambling::Trie::Stringifyable do
6
6
  describe '#as_word' do
7
7
  let(:node) { Rambling::Trie::Nodes::Raw.new }
8
8
 
9
- context 'for an empty node' do
10
- before do
11
- add_word node, ''
12
- end
9
+ context 'with an empty node' do
10
+ before { add_word node, '' }
13
11
 
14
12
  it 'returns nil' do
15
13
  expect(node.as_word).to be_empty
16
14
  end
17
15
  end
18
16
 
19
- context 'for one letter' do
17
+ context 'with one letter' do
20
18
  before do
21
19
  node.letter = :a
22
20
  add_word node, ''
@@ -27,7 +25,7 @@ describe Rambling::Trie::Stringifyable do
27
25
  end
28
26
  end
29
27
 
30
- context 'for a small word' do
28
+ context 'with a small word' do
31
29
  before do
32
30
  node.letter = :a
33
31
  add_word node, 'll'
@@ -43,7 +41,7 @@ describe Rambling::Trie::Stringifyable do
43
41
  end
44
42
  end
45
43
 
46
- context 'for a long word' do
44
+ context 'with a long word' do
47
45
  before do
48
46
  node.letter = :b
49
47
  add_word node, 'eautiful'
@@ -54,7 +52,7 @@ describe Rambling::Trie::Stringifyable do
54
52
  end
55
53
  end
56
54
 
57
- context 'for a node with nil letter' do
55
+ context 'with a node with nil letter' do
58
56
  let(:node) { Rambling::Trie::Nodes::Raw.new nil }
59
57
 
60
58
  it 'returns nil' do
@@ -62,7 +60,7 @@ describe Rambling::Trie::Stringifyable do
62
60
  end
63
61
  end
64
62
 
65
- context 'for a compressed node' do
63
+ context 'with a compressed node' do
66
64
  let(:compressor) { Rambling::Trie::Compressor.new }
67
65
  let(:compressed_node) { compressor.compress node }
68
66
 
@@ -71,12 +69,18 @@ describe Rambling::Trie::Stringifyable do
71
69
  add_words node, %w(m dd)
72
70
  end
73
71
 
74
- it 'returns the words for the terminal nodes' do
75
- expect(compressed_node[:m].as_word).to eq 'am'
76
- expect(compressed_node[:d].as_word).to eq 'add'
72
+ [
73
+ [:m, 'am'],
74
+ [:d, 'add'],
75
+ ].each do |test_params|
76
+ key, expected = test_params
77
+
78
+ it "returns the words for terminal nodes (#{key} => #{expected})" do
79
+ expect(compressed_node[key].as_word).to eq expected
80
+ end
77
81
  end
78
82
 
79
- it 'raise an error for non terminal nodes' do
83
+ it 'raises an error for non terminal nodes' do
80
84
  expect { compressed_node.as_word }
81
85
  .to raise_error Rambling::Trie::InvalidOperation
82
86
  end