LittleWeasel 3.0.3 → 5.0.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 (151) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.reek.yml +17 -0
  4. data/.rspec +4 -2
  5. data/.rubocop.yml +187 -0
  6. data/.ruby-version +1 -1
  7. data/.yardopts +2 -0
  8. data/CHANGELOG.md +22 -1
  9. data/Gemfile +3 -1
  10. data/Jenkinsfile +20 -0
  11. data/LittleWeasel.gemspec +31 -18
  12. data/README.md +408 -42
  13. data/Rakefile +296 -3
  14. data/lib/LittleWeasel/block_results.rb +81 -0
  15. data/lib/LittleWeasel/configure.rb +98 -0
  16. data/lib/LittleWeasel/dictionary.rb +125 -0
  17. data/lib/LittleWeasel/dictionary_key.rb +48 -0
  18. data/lib/LittleWeasel/dictionary_manager.rb +91 -0
  19. data/lib/LittleWeasel/errors/dictionary_file_already_loaded_error.rb +9 -0
  20. data/lib/LittleWeasel/errors/dictionary_file_empty_error.rb +8 -0
  21. data/lib/LittleWeasel/errors/dictionary_file_not_found_error.rb +8 -0
  22. data/lib/LittleWeasel/errors/dictionary_file_too_large_error.rb +16 -0
  23. data/lib/LittleWeasel/errors/language_required_error.rb +8 -0
  24. data/lib/LittleWeasel/errors/must_override_error.rb +8 -0
  25. data/lib/LittleWeasel/filters/en_us/currency_filter.rb +19 -0
  26. data/lib/LittleWeasel/filters/en_us/numeric_filter.rb +19 -0
  27. data/lib/LittleWeasel/filters/en_us/single_character_word_filter.rb +21 -0
  28. data/lib/LittleWeasel/filters/word_filter.rb +59 -0
  29. data/lib/LittleWeasel/filters/word_filter_managable.rb +80 -0
  30. data/lib/LittleWeasel/filters/word_filter_validatable.rb +31 -0
  31. data/lib/LittleWeasel/filters/word_filterable.rb +19 -0
  32. data/lib/LittleWeasel/filters/word_filters_validatable.rb +29 -0
  33. data/lib/LittleWeasel/metadata/dictionary_metadata.rb +145 -0
  34. data/lib/LittleWeasel/metadata/invalid_words_metadata.rb +134 -0
  35. data/lib/LittleWeasel/metadata/invalid_words_service_results.rb +45 -0
  36. data/lib/LittleWeasel/metadata/metadata_observable_validatable.rb +22 -0
  37. data/lib/LittleWeasel/metadata/metadata_observerable.rb +90 -0
  38. data/lib/LittleWeasel/metadata/metadatable.rb +134 -0
  39. data/lib/LittleWeasel/modules/class_name_to_symbol.rb +26 -0
  40. data/lib/LittleWeasel/modules/configurable.rb +26 -0
  41. data/lib/LittleWeasel/modules/deep_dup.rb +11 -0
  42. data/lib/LittleWeasel/modules/dictionary_cache_keys.rb +34 -0
  43. data/lib/LittleWeasel/modules/dictionary_cache_servicable.rb +26 -0
  44. data/lib/LittleWeasel/modules/dictionary_cache_validatable.rb +18 -0
  45. data/lib/LittleWeasel/modules/dictionary_creator_servicable.rb +27 -0
  46. data/lib/LittleWeasel/modules/dictionary_file_loader.rb +67 -0
  47. data/lib/LittleWeasel/modules/dictionary_key_validatable.rb +17 -0
  48. data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
  49. data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
  50. data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +15 -0
  51. data/lib/LittleWeasel/modules/dictionary_source_validatable.rb +15 -0
  52. data/lib/LittleWeasel/modules/dictionary_sourceable.rb +86 -0
  53. data/lib/LittleWeasel/modules/dictionary_validatable.rb +18 -0
  54. data/lib/LittleWeasel/modules/language.rb +24 -0
  55. data/lib/LittleWeasel/modules/language_validatable.rb +14 -0
  56. data/lib/LittleWeasel/modules/locale.rb +23 -0
  57. data/lib/LittleWeasel/modules/order_validatable.rb +16 -0
  58. data/lib/LittleWeasel/modules/orderable.rb +17 -0
  59. data/lib/LittleWeasel/modules/region.rb +24 -0
  60. data/lib/LittleWeasel/modules/region_validatable.rb +14 -0
  61. data/lib/LittleWeasel/modules/tag_validatable.rb +14 -0
  62. data/lib/LittleWeasel/modules/taggable.rb +31 -0
  63. data/lib/LittleWeasel/modules/word_results_validatable.rb +28 -0
  64. data/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor.rb +22 -0
  65. data/lib/LittleWeasel/preprocessors/preprocessed_word.rb +29 -0
  66. data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +56 -0
  67. data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +59 -0
  68. data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +28 -0
  69. data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
  70. data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +123 -0
  71. data/lib/LittleWeasel/preprocessors/word_preprocessor_managable.rb +114 -0
  72. data/lib/LittleWeasel/preprocessors/word_preprocessor_validatable.rb +40 -0
  73. data/lib/LittleWeasel/preprocessors/word_preprocessors_validatable.rb +24 -0
  74. data/lib/LittleWeasel/services/dictionary_cache_service.rb +211 -0
  75. data/lib/LittleWeasel/services/dictionary_creator_service.rb +94 -0
  76. data/lib/LittleWeasel/services/dictionary_file_loader_service.rb +37 -0
  77. data/lib/LittleWeasel/services/dictionary_killer_service.rb +35 -0
  78. data/lib/LittleWeasel/services/dictionary_metadata_service.rb +116 -0
  79. data/lib/LittleWeasel/services/invalid_words_service.rb +59 -0
  80. data/lib/LittleWeasel/version.rb +3 -1
  81. data/lib/LittleWeasel/word_results.rb +146 -0
  82. data/lib/LittleWeasel.rb +5 -184
  83. data/spec/factories/dictionary.rb +43 -0
  84. data/spec/factories/dictionary_cache_service.rb +95 -0
  85. data/spec/factories/dictionary_creator_service.rb +16 -0
  86. data/spec/factories/dictionary_file_loader_service.rb +13 -0
  87. data/spec/factories/dictionary_hash.rb +39 -0
  88. data/spec/factories/dictionary_key.rb +14 -0
  89. data/spec/factories/dictionary_killer_service.rb +14 -0
  90. data/spec/factories/dictionary_manager.rb +10 -0
  91. data/spec/factories/dictionary_metadata.rb +16 -0
  92. data/spec/factories/dictionary_metadata_service.rb +16 -0
  93. data/spec/factories/numeric_filter.rb +12 -0
  94. data/spec/factories/preprocessed_word.rb +16 -0
  95. data/spec/factories/preprocessed_words.rb +41 -0
  96. data/spec/factories/single_character_word_filter.rb +12 -0
  97. data/spec/factories/word_results.rb +16 -0
  98. data/spec/lib/LittleWeasel/block_results_spec.rb +248 -0
  99. data/spec/lib/LittleWeasel/configure_spec.rb +74 -0
  100. data/spec/lib/LittleWeasel/dictionary_key_spec.rb +118 -0
  101. data/spec/lib/LittleWeasel/dictionary_manager_spec.rb +166 -0
  102. data/spec/lib/LittleWeasel/dictionary_spec.rb +289 -0
  103. data/spec/lib/LittleWeasel/filters/en_us/currency_filter_spec.rb +80 -0
  104. data/spec/lib/LittleWeasel/filters/en_us/numeric_filter_spec.rb +66 -0
  105. data/spec/lib/LittleWeasel/filters/en_us/single_character_word_filter_spec.rb +58 -0
  106. data/spec/lib/LittleWeasel/filters/word_filter_managable_spec.rb +180 -0
  107. data/spec/lib/LittleWeasel/filters/word_filter_spec.rb +151 -0
  108. data/spec/lib/LittleWeasel/filters/word_filter_validatable_spec.rb +94 -0
  109. data/spec/lib/LittleWeasel/filters/word_filters_validatable_spec.rb +48 -0
  110. data/spec/lib/LittleWeasel/integraton_tests/dictionary_integration_spec.rb +201 -0
  111. data/spec/lib/LittleWeasel/metadata/dictionary_creator_servicable_spec.rb +54 -0
  112. data/spec/lib/LittleWeasel/metadata/dictionary_metadata_spec.rb +209 -0
  113. data/spec/lib/LittleWeasel/metadata/invalid_words_metadata_spec.rb +155 -0
  114. data/spec/lib/LittleWeasel/metadata/metadata_observerable_spec.rb +31 -0
  115. data/spec/lib/LittleWeasel/metadata/metadatable_spec.rb +35 -0
  116. data/spec/lib/LittleWeasel/modules/class_name_to_symbol_spec.rb +21 -0
  117. data/spec/lib/LittleWeasel/modules/dictionary_file_loader_spec.rb +125 -0
  118. data/spec/lib/LittleWeasel/modules/dictionary_sourceable_spec.rb +81 -0
  119. data/spec/lib/LittleWeasel/modules/language_spec.rb +112 -0
  120. data/spec/lib/LittleWeasel/modules/locale_spec.rb +95 -0
  121. data/spec/lib/LittleWeasel/modules/region_spec.rb +112 -0
  122. data/spec/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor_spec.rb +34 -0
  123. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_spec.rb +105 -0
  124. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_validatable_spec.rb +143 -0
  125. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_spec.rb +77 -0
  126. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_validatable_spec.rb +58 -0
  127. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_managable_spec.rb +242 -0
  128. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +218 -0
  129. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_validatable_spec.rb +109 -0
  130. data/spec/lib/LittleWeasel/preprocessors/word_preprocessors_validatable_spec.rb +49 -0
  131. data/spec/lib/LittleWeasel/services/dictionary_cache_service_spec.rb +444 -0
  132. data/spec/lib/LittleWeasel/services/dictionary_creator_service_spec.rb +119 -0
  133. data/spec/lib/LittleWeasel/services/dictionary_file_loader_service_spec.rb +71 -0
  134. data/spec/lib/LittleWeasel/services/dictionary_metadata_service_spec.rb +279 -0
  135. data/spec/lib/LittleWeasel/word_results_spec.rb +275 -0
  136. data/spec/lib/LittleWeasel/workflow/workflow_spec.rb +20 -0
  137. data/spec/spec_helper.rb +117 -6
  138. data/spec/support/factory_bot.rb +15 -0
  139. data/spec/support/file_helpers.rb +46 -0
  140. data/spec/support/files/empty-dictionary.txt +0 -0
  141. data/{lib/dictionary → spec/support/files/en-US-big.txt} +262156 -31488
  142. data/spec/support/files/en-US-tagged.txt +26 -0
  143. data/spec/support/files/en-US.txt +26 -0
  144. data/spec/support/files/en.txt +26 -0
  145. data/spec/support/files/es-ES.txt +27 -0
  146. data/spec/support/files/es.txt +27 -0
  147. data/spec/support/general_helpers.rb +68 -0
  148. data/spec/support/shared_contexts.rb +107 -0
  149. data/spec/support/shared_examples.rb +105 -0
  150. metadata +378 -38
  151. data/spec/checker/checker_spec.rb +0 -286
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::PreprocessedWords, type: :module do
6
+ subject { create(:preprocessed_words, original_word: original_word, preprocessed_words: preprocessed_words) }
7
+
8
+ let(:original_word) { 'word' }
9
+ let(:preprocessed_words) {}
10
+
11
+ #.new
12
+ describe '.new' do
13
+ it 'instantiates an object' do
14
+ expect { subject }.to_not raise_error
15
+ end
16
+
17
+ context 'arguments' do
18
+ context '#original_word' do
19
+ it 'sets the original_word attribute' do
20
+ expect(subject.original_word).to eq original_word
21
+ end
22
+ end
23
+
24
+ context '#preprocessed_words' do
25
+ let(:preprocessed_words) { [:preprocessed_words] }
26
+
27
+ it 'sets the original_word attribute' do
28
+ expect(subject.preprocessed_words).to eq preprocessed_words
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ #preprocessed_word
35
+ describe '#preprocessed_word' do
36
+ subject do
37
+ create(:preprocessed_words,
38
+ with_word_processors: 3,
39
+ original_word: original_word,
40
+ preprocessed_words: preprocessed_words)
41
+ end
42
+
43
+ it 'returns the preprocessed word' do
44
+ expect(subject.preprocessed_word).to eq 'word-0-1-2'
45
+ end
46
+ end
47
+
48
+ #preprocessed?
49
+ describe '#preprocessed?' do
50
+ context 'when the word has been preprocessed' do
51
+ subject do
52
+ create(:preprocessed_words,
53
+ with_word_processors: 1,
54
+ original_word: original_word,
55
+ preprocessed_words: preprocessed_words)
56
+ end
57
+
58
+ it 'returns the preprocessed word' do
59
+ expect(subject.preprocessed?).to eq true
60
+ end
61
+ end
62
+
63
+ context 'when the word has NOT been preprocessed' do
64
+ subject do
65
+ create(:preprocessed_words,
66
+ original_word: original_word,
67
+ preprocessed_words: preprocessed_words)
68
+ end
69
+
70
+ it 'returns the preprocessed word' do
71
+ expect(subject.preprocessed?).to eq false
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::PreprocessedWordsValidatable, type: :module do
6
+ PreprocessedWordsValidatable = described_class
7
+
8
+ class MockSubject
9
+ include PreprocessedWordsValidatable
10
+ end
11
+
12
+ subject do
13
+ MockSubject.new
14
+ end
15
+
16
+ before do
17
+ allow(preprocessed_words).to receive(:respond_to?).and_call_original
18
+ end
19
+
20
+ let(:preprocessed_words) do
21
+ create(:preprocessed_words,
22
+ original_word: original_word,
23
+ with_word_processors: with_word_processors)
24
+ end
25
+ let(:original_word) { 'word' }
26
+ let(:with_word_processors) { 0 }
27
+
28
+ #.validate_prepreprocessed_words
29
+ describe '.validate_prepreprocessed_words' do
30
+ context 'when the object is valid' do
31
+ it 'does not raise an error' do
32
+ expect { PreprocessedWordsValidatable.validate_prepreprocessed_words(preprocessed_words: preprocessed_words) }.to_not raise_error
33
+ end
34
+ end
35
+
36
+ context 'when the object is INVALID' do
37
+ let(:expected_error) { /Argument preprocessed_words does not respond to:.+##{method}/ }
38
+
39
+ context 'when the object does not respond to #original_word' do
40
+ before { allow(preprocessed_words).to receive(:respond_to?).with(method).and_return(false) }
41
+ let(:method) { :original_word }
42
+
43
+ it 'raises an error' do
44
+ expect{ PreprocessedWordsValidatable.validate_prepreprocessed_words(preprocessed_words: preprocessed_words) }.to raise_error expected_error
45
+ end
46
+ end
47
+
48
+ context 'when the object does not respond to #preprocessed_words' do
49
+ before { allow(preprocessed_words).to receive(:respond_to?).with(method).and_return(false) }
50
+ let(:method) { :preprocessed_words }
51
+
52
+ it 'raises an error' do
53
+ expect{ PreprocessedWordsValidatable.validate_prepreprocessed_words(preprocessed_words: preprocessed_words) }.to raise_error expected_error
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,242 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::WordPreprocessorManagable, type: :module do
6
+ subject { MockSubject.new }
7
+
8
+ WordPreprocessorManagable = described_class
9
+
10
+ class MockSubject
11
+ include WordPreprocessorManagable
12
+ end
13
+
14
+ class MockWordPreprocessor01 < LittleWeasel::Preprocessors::WordPreprocessor
15
+ def initialize(order: 0)
16
+ super order: order
17
+ end
18
+
19
+ class << self
20
+ def preprocess(word) [true, "#{word}-0"]; end
21
+ end
22
+ end
23
+
24
+ class MockWordPreprocessor02 < MockWordPreprocessor01
25
+ def initialize
26
+ super order: 1
27
+ end
28
+
29
+ class << self
30
+ def preprocess(word) [true, "#{word}-1"]; end
31
+ end
32
+ end
33
+
34
+ class MockWordPreprocessor03 < MockWordPreprocessor01
35
+ def initialize
36
+ super order: 2
37
+ end
38
+
39
+ class << self
40
+ def preprocess(word) [true, "#{word}-2"]; end
41
+ end
42
+ end
43
+
44
+ let(:word_preprocessors_01_thru_03) do
45
+ [MockWordPreprocessor03.new,
46
+ MockWordPreprocessor02.new,
47
+ MockWordPreprocessor01.new]
48
+ end
49
+
50
+ class MockWordPreprocessor04 < MockWordPreprocessor01
51
+ def initialize
52
+ super order: 3
53
+ end
54
+
55
+ class << self
56
+ def preprocess(word) [true, "#{word}-3"]; end
57
+ end
58
+ end
59
+
60
+ class MockWordPreprocessor05 < MockWordPreprocessor01
61
+ def initialize
62
+ super order: 4
63
+ end
64
+
65
+ class << self
66
+ def preprocess(word) [true, "#{word}-4"]; end
67
+ end
68
+ end
69
+
70
+ class MockWordPreprocessor06 < MockWordPreprocessor01
71
+ def initialize
72
+ super order: 5
73
+ end
74
+
75
+ class << self
76
+ def preprocess(word) [true, "#{word}-5"]; end
77
+ end
78
+ end
79
+
80
+ let(:word_preprocessors_04_thru_06) do
81
+ [MockWordPreprocessor06.new,
82
+ MockWordPreprocessor05.new,
83
+ MockWordPreprocessor04.new]
84
+ end
85
+
86
+ #preprocessed_word
87
+ describe '#preprocessed_word' do
88
+ context 'when word is blank' do
89
+ it 'returns nil' do
90
+ expect(subject.preprocessed_word word: 'word').to be_nil
91
+ end
92
+ end
93
+
94
+ context 'when word is not a String' do
95
+ it 'returns nil' do
96
+ expect(subject.preprocessed_word word: :not_a_word).to be_nil
97
+ end
98
+ end
99
+
100
+ context 'when word is NOT blank' do
101
+ before do
102
+ subject.replace_preprocessors word_preprocessors: word_preprocessors_01_thru_03
103
+ end
104
+
105
+ it 'returns the preprocessed word' do
106
+ expect(subject.preprocessed_word word: 'word').to eq 'word-0-1-2'
107
+ end
108
+ end
109
+ end
110
+
111
+ #word_preprocessors
112
+ describe '#word_preprocessors' do
113
+ it 'returns an empty Array ([]) by default' do
114
+ expect(subject.word_preprocessors).to eq []
115
+ end
116
+ end
117
+
118
+ #clear_preprocessors
119
+ describe '#clear_preprocessors' do
120
+ before do
121
+ subject.replace_preprocessors word_preprocessors: word_preprocessors_01_thru_03
122
+ end
123
+
124
+ it 'clears #word_preprocessors' do
125
+ expect { subject.clear_preprocessors }.to change { subject.word_preprocessors.count }.from(3).to(0)
126
+ end
127
+ end
128
+
129
+ #add_preprocessors
130
+ describe '#add_preprocessors' do
131
+ context 'when passing an INVALID argument' do
132
+ context 'when passing an Array of invalid word preprocessors' do
133
+ it 'raises an error' do
134
+ expect { subject.add_preprocessors(word_preprocessors: %i(bad word preprocessors)) }.to raise_error(/Argument word_preprocessor: does not respond to/)
135
+ end
136
+ end
137
+ end
138
+
139
+ context 'when passing a valid argument' do
140
+ before do
141
+ subject.replace_preprocessors word_preprocessors: word_preprocessors_04_thru_06
142
+ end
143
+
144
+ let(:expected_results) do
145
+ word_preprocessors_01_thru_03.concat(word_preprocessors_04_thru_06).sort_by(&:order)
146
+ end
147
+
148
+ it 'adds the word preprocessors to the #word_preprocessors and sorts the #word_preprocessors Array by WordPreprocessor#order' do
149
+ expect { subject.add_preprocessors word_preprocessors: word_preprocessors_01_thru_03 }.to \
150
+ change { subject.word_preprocessors.count }.from(3).to(6)
151
+ expect(subject.word_preprocessors).to eq expected_results
152
+ end
153
+ end
154
+
155
+ context 'when passing a nil argument' do
156
+ before do
157
+ subject.clear_preprocessors
158
+ end
159
+
160
+ context 'when a block is provided' do
161
+ it 'does NOT raise an error' do
162
+ expect do
163
+ subject.add_preprocessors { |_word_preprocessors| }
164
+ end.to_not raise_error
165
+ end
166
+
167
+ it 'uses the word preprocessors added via the block' do
168
+ expect do
169
+ subject.add_preprocessors do |word_preprocessors|
170
+ word_preprocessors.concat word_preprocessors_01_thru_03
171
+ end
172
+ end.to change { subject.word_preprocessors.count }.from(0).to(3)
173
+ end
174
+ end
175
+
176
+ context 'when a block is NOT provided' do
177
+ it 'raises an error' do
178
+ expect { subject.add_preprocessors }.to raise_error('A block is required if argument word_preprocessors is nil')
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ #replace_preprocessors
185
+ describe '#replace_preprocessors' do
186
+ before do
187
+ subject.add_preprocessors word_preprocessors: word_preprocessors_01_thru_03
188
+ end
189
+
190
+ let(:expected_results) do
191
+ word_preprocessors_04_thru_06.sort_by(&:order)
192
+ end
193
+
194
+ it 'replaces the word preprocessors in #word_preprocessors and sorts the #word_preprocessors Array by WordPreprocessor#order' do
195
+ expect(subject.word_preprocessors).to match_array word_preprocessors_01_thru_03
196
+ expect(subject.replace_preprocessors word_preprocessors: word_preprocessors_04_thru_06).to eq expected_results
197
+ expect(subject.word_preprocessors).to eq expected_results
198
+ end
199
+ end
200
+
201
+ #preprocessors_on=
202
+ describe '#preprocessors_on=' do
203
+ context 'when assigning true' do
204
+ before do
205
+ subject.preprocessors_on = false
206
+ expect(subject.word_preprocessors.map(&:preprocessor_on)).to all(be false)
207
+ end
208
+
209
+ it 'sets all preprocessors on' do
210
+ subject.preprocessors_on = true
211
+ expect(subject.word_preprocessors.map(&:preprocessor_on)).to all(be true)
212
+ end
213
+ end
214
+
215
+ context 'when assigning false' do
216
+ before do
217
+ subject.preprocessors_on = true
218
+ expect(subject.word_preprocessors.map(&:preprocessor_on)).to all(be true)
219
+ end
220
+
221
+ it 'sets all preprocessors off' do
222
+ subject.preprocessors_on = false
223
+ expect(subject.word_preprocessors.map(&:preprocessor_on)).to all(be false)
224
+ end
225
+ end
226
+ end
227
+
228
+ #preprocess
229
+ describe '#preprocess' do
230
+ before do
231
+ subject.add_preprocessors word_preprocessors: word_preprocessors
232
+ end
233
+
234
+ let(:word) { 'word' }
235
+ let(:word_preprocessors) { word_preprocessors_01_thru_03 }
236
+
237
+ it 'preprocesses the word' do
238
+ expect(subject.word_preprocessors.count).to eq word_preprocessors.count
239
+ expect(subject.preprocess(word: word).preprocessed_words.map(&:preprocessed_word)).to eq %w(word-0 word-0-1 word-0-1-2)
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,218 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::WordPreprocessor do
6
+ subject do
7
+ word_preprocessor = described_class.new order: order
8
+ word_preprocessor.preprocessor_on = preprocessor_on
9
+ word_preprocessor
10
+ end
11
+
12
+ let(:preprocessor_on) { true }
13
+ let(:order) { 0 }
14
+ let(:word) { 'word' }
15
+
16
+ #.new
17
+ describe '.new' do
18
+ context 'when arguments are valid' do
19
+ it 'instantiates the object' do
20
+ expect { subject }.to_not raise_error
21
+ end
22
+ end
23
+
24
+ context 'when arguments are INVALID' do
25
+ context 'when argument order is invalid' do
26
+ context 'when order is not an Integer' do
27
+ let(:order) { :not_an_integer }
28
+
29
+ it 'raises an error' do
30
+ expect { subject }.to raise_error(/Argument order is not an Integer/)
31
+ end
32
+ end
33
+
34
+ context 'when order is negative' do
35
+ let(:order) { -1 }
36
+
37
+ it 'raises an error' do
38
+ expect { subject }.to raise_error "Argument order '#{order}' is not a a number from 0-n"
39
+ end
40
+ end
41
+ end
42
+
43
+ context 'when argument preprocessor_on is invalid' do
44
+ context 'when preprocessor_on is not true or false' do
45
+ let(:preprocessor_on) { :not_true_or_false }
46
+
47
+ it 'raises an error' do
48
+ expect { subject }.to raise_error "Argument value is not true or false: #{preprocessor_on}"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ #.preprocess
56
+ describe '.preprocess' do
57
+ context 'when not overridden' do
58
+ it 'raises an error' do
59
+ expect { subject.class.preprocess word }.to raise_error LittleWeasel::Errors::MustOverrideError
60
+ end
61
+ end
62
+ end
63
+
64
+ #preprocessor_on
65
+ describe '#preprocessor_on' do
66
+ context 'when set to true' do
67
+ before do
68
+ subject.preprocessor_on = true
69
+ end
70
+
71
+ it 'returns true' do
72
+ expect(subject.preprocessor_on).to eq true
73
+ end
74
+ end
75
+
76
+ context 'when set to false' do
77
+ before do
78
+ subject.preprocessor_on = false
79
+ end
80
+
81
+ it 'returns false' do
82
+ expect(subject.preprocessor_on).to eq false
83
+ end
84
+ end
85
+ end
86
+
87
+ #preprocessor_on!
88
+ describe '#preprocessor_on!' do
89
+ before do
90
+ expect(subject.preprocessor_off?).to eq true
91
+ end
92
+
93
+ let(:preprocessor_on) { false }
94
+
95
+ it 'turns the preprocessor on' do
96
+ subject.preprocessor_on!
97
+ expect(subject.preprocessor_on).to eq true
98
+ end
99
+ end
100
+
101
+ #preprocessor_on?
102
+ describe '#preprocessor_on?' do
103
+ context 'when #preprocessor_on is true' do
104
+ it 'returns true' do
105
+ expect(subject.preprocessor_on?).to eq true
106
+ end
107
+ end
108
+
109
+ context 'when #preprocessor_on is false' do
110
+ let(:preprocessor_on) { false }
111
+
112
+ it 'returns false' do
113
+ expect(subject.preprocessor_on?).to eq false
114
+ end
115
+ end
116
+ end
117
+
118
+ #preprocess
119
+ describe '#preprocess' do
120
+ context 'when not overridden' do
121
+ it 'raises an error' do
122
+ expect { subject.preprocess 'x' }.to raise_error LittleWeasel::Errors::MustOverrideError
123
+ end
124
+ end
125
+
126
+ context 'when overridden' do
127
+ before do
128
+ allow(described_class).to receive(:preprocess?)
129
+ .and_return true
130
+ allow(described_class).to receive(:preprocess)
131
+ .and_return [true, 'preprocessed-word']
132
+ end
133
+
134
+ context 'when #preprocessor_on? is true' do
135
+ it 'calls .preprocess and returns a ProcessedWord object' do
136
+ expect(described_class).to receive(:preprocess)
137
+ expect(subject.preprocess word).to be_kind_of LittleWeasel::Preprocessors::PreprocessedWord
138
+ end
139
+ end
140
+
141
+ context 'when #preprocessor_on? is false' do
142
+ let(:preprocessor_on) { false }
143
+
144
+ it 'does NOT call .preprocess and returns a ProcessedWord object' do
145
+ expect(described_class).to_not receive(:preprocess)
146
+ expect(subject.preprocess word).to be_kind_of LittleWeasel::Preprocessors::PreprocessedWord
147
+ end
148
+
149
+ end
150
+ end
151
+ end
152
+
153
+ #preprocess?
154
+ describe '#preprocess?' do
155
+ let(:word) { 'word' }
156
+
157
+ it 'returns true by default' do
158
+ expect(subject.preprocess? word).to be true
159
+ end
160
+
161
+ context 'when #preprocess? returns true' do
162
+ before { allow(subject.class).to receive(:preprocess?).and_return(true) }
163
+
164
+ context 'when #preprocessor_on? is true' do
165
+ it_behaves_like 'the preprocessor matches and #preprocessor_on? is true'
166
+ end
167
+
168
+ context 'when #preprocessor_on? is false' do
169
+ let(:preprocessor_on) { false }
170
+
171
+ it_behaves_like 'the preprocessor matches and #preprocessor_on? is false'
172
+ end
173
+ end
174
+
175
+ context 'when #preprocess? returns false' do
176
+ before { allow(subject.class).to receive(:preprocess?).and_return(false) }
177
+
178
+ context 'when #preprocessor_on? is true' do
179
+ it_behaves_like 'the preprocessor DOES NOT match and #preprocessor_on? is true'
180
+ end
181
+
182
+ context 'when #preprocessor_on? is false' do
183
+ let(:preprocessor_on) { false }
184
+
185
+ it_behaves_like 'the preprocessor DOES NOT match and #preprocessor_on? is false'
186
+ end
187
+ end
188
+ end
189
+
190
+ #preprocessor_off?
191
+ describe '#preprocessor_off?' do
192
+ context 'when #preprocessor_on is false' do
193
+ let(:preprocessor_on) { false }
194
+
195
+ it 'returns true' do
196
+ expect(subject.preprocessor_off?).to eq true
197
+ end
198
+ end
199
+
200
+ context 'when #preprocessor_on is true' do
201
+ it 'returns false' do
202
+ expect(subject.preprocessor_off?).to eq false
203
+ end
204
+ end
205
+ end
206
+
207
+ #preprocessor_off!
208
+ describe '#preprocessor_off!' do
209
+ before do
210
+ expect(subject.preprocessor_on?).to eq true
211
+ end
212
+
213
+ it 'turns the preprocessor off' do
214
+ subject.preprocessor_off!
215
+ expect(subject.preprocessor_on).to eq false
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::WordPreprocessorValidatable, type: :module do
6
+ subject { MockSubject.new }
7
+
8
+ WordPreprocessorValidatable = described_class
9
+
10
+ class MockSubject
11
+ include WordPreprocessorValidatable
12
+ end
13
+
14
+ class MockWordPreprocessor < LittleWeasel::Preprocessors::WordPreprocessor
15
+ def preprocess(word)
16
+ [true, "#{word}-preprocessed"]
17
+ end
18
+ end
19
+
20
+ let(:order) { 0 }
21
+ let(:preprocessor_on) { true }
22
+ let(:word_preprocessor) do
23
+ word_preprocessor = MockWordPreprocessor.new order: order
24
+ word_preprocessor.preprocessor_on = preprocessor_on
25
+ word_preprocessor
26
+ end
27
+
28
+ shared_examples 'an instance method is missing' do
29
+ before do
30
+ allow(word_preprocessor).to receive(:respond_to?).with(method).and_return(false)
31
+ end
32
+
33
+ it 'raises an error' do
34
+ expect { WordPreprocessorValidatable.validate_word_preprocessor word_preprocessor: word_preprocessor }.to raise_error expected_error_message
35
+ end
36
+ end
37
+
38
+ shared_examples 'a class method is missing' do
39
+ before do
40
+ allow(word_preprocessor.class).to receive(:respond_to?).with(method).and_return(false)
41
+ end
42
+
43
+ it 'raises an error' do
44
+ expect { WordPreprocessorValidatable.validate_word_preprocessor word_preprocessor: word_preprocessor }.to raise_error expected_error_message
45
+ end
46
+ end
47
+
48
+ #.validate_word_preprocessor
49
+ describe '.validate_word_preprocessor' do
50
+ before do
51
+ allow(word_preprocessor.class).to receive(:respond_to?).and_call_original
52
+ allow(word_preprocessor).to receive(:respond_to?).and_call_original
53
+ end
54
+
55
+ context 'when the object quacks right' do
56
+ it 'passes validation' do
57
+ expect { WordPreprocessorValidatable.validate_word_preprocessor word_preprocessor: word_preprocessor }.to_not raise_error
58
+ end
59
+ end
60
+
61
+ context 'when the object DOES NOT quack right' do
62
+ let(:expected_error_message) { /Argument word_preprocessor: does not respond to/ }
63
+
64
+ context 'when a class method is missing' do
65
+ context 'when the class does not respond to .preprocess' do
66
+ let(:method) { :preprocess }
67
+ it_behaves_like 'a class method is missing'
68
+ end
69
+
70
+ context 'when the class does not respond to .preprocess?' do
71
+ let(:method) { :preprocess? }
72
+ it_behaves_like 'a class method is missing'
73
+ end
74
+ end
75
+
76
+ context 'when an instance method is missing' do
77
+ context 'when the object does not respond to #preprocess' do
78
+ let(:method) { :preprocess }
79
+ it_behaves_like 'an instance method is missing'
80
+ end
81
+
82
+ context 'when the object does not respond to #preprocess?' do
83
+ let(:method) { :preprocess? }
84
+ it_behaves_like 'an instance method is missing'
85
+ end
86
+
87
+ context 'when the object does not respond to #preprocessor_off?' do
88
+ let(:method) { :preprocessor_off? }
89
+ it_behaves_like 'an instance method is missing'
90
+ end
91
+
92
+ context 'when the object does not respond to #preprocessor_on' do
93
+ let(:method) { :preprocessor_on }
94
+ it_behaves_like 'an instance method is missing'
95
+ end
96
+
97
+ context 'when the object does not respond to #preprocessor_on=' do
98
+ let(:method) { :preprocessor_on= }
99
+ it_behaves_like 'an instance method is missing'
100
+ end
101
+
102
+ context 'when the object does not respond to #preprocessor_on?' do
103
+ let(:method) { :preprocessor_on? }
104
+ it_behaves_like 'an instance method is missing'
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end