LittleWeasel 3.0.4 → 5.0.1
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.
- checksums.yaml +5 -5
- data/.github/workflows/codeql-analysis.yml +72 -0
- data/.gitignore +19 -17
- data/.reek.yml +17 -0
- data/.rspec +4 -2
- data/.rubocop.yml +187 -0
- data/.ruby-version +1 -1
- data/.yardopts +2 -0
- data/CHANGELOG.md +21 -1
- data/Gemfile +3 -1
- data/Gemfile.lock +114 -0
- data/Jenkinsfile +20 -0
- data/LittleWeasel.gemspec +31 -18
- data/README.md +408 -42
- data/Rakefile +296 -3
- data/lib/LittleWeasel/block_results.rb +81 -0
- data/lib/LittleWeasel/configure.rb +98 -0
- data/lib/LittleWeasel/dictionary.rb +125 -0
- data/lib/LittleWeasel/dictionary_key.rb +48 -0
- data/lib/LittleWeasel/dictionary_manager.rb +91 -0
- data/lib/LittleWeasel/errors/dictionary_file_already_loaded_error.rb +9 -0
- data/lib/LittleWeasel/errors/dictionary_file_empty_error.rb +8 -0
- data/lib/LittleWeasel/errors/dictionary_file_not_found_error.rb +8 -0
- data/lib/LittleWeasel/errors/dictionary_file_too_large_error.rb +16 -0
- data/lib/LittleWeasel/errors/language_required_error.rb +8 -0
- data/lib/LittleWeasel/errors/must_override_error.rb +8 -0
- data/lib/LittleWeasel/filters/en_us/currency_filter.rb +19 -0
- data/lib/LittleWeasel/filters/en_us/numeric_filter.rb +19 -0
- data/lib/LittleWeasel/filters/en_us/single_character_word_filter.rb +21 -0
- data/lib/LittleWeasel/filters/word_filter.rb +59 -0
- data/lib/LittleWeasel/filters/word_filter_managable.rb +80 -0
- data/lib/LittleWeasel/filters/word_filter_validatable.rb +31 -0
- data/lib/LittleWeasel/filters/word_filterable.rb +19 -0
- data/lib/LittleWeasel/filters/word_filters_validatable.rb +29 -0
- data/lib/LittleWeasel/metadata/dictionary_metadata.rb +145 -0
- data/lib/LittleWeasel/metadata/invalid_words_metadata.rb +134 -0
- data/lib/LittleWeasel/metadata/invalid_words_service_results.rb +45 -0
- data/lib/LittleWeasel/metadata/metadata_observable_validatable.rb +22 -0
- data/lib/LittleWeasel/metadata/metadata_observerable.rb +90 -0
- data/lib/LittleWeasel/metadata/metadatable.rb +134 -0
- data/lib/LittleWeasel/modules/class_name_to_symbol.rb +26 -0
- data/lib/LittleWeasel/modules/configurable.rb +26 -0
- data/lib/LittleWeasel/modules/deep_dup.rb +11 -0
- data/lib/LittleWeasel/modules/dictionary_cache_keys.rb +34 -0
- data/lib/LittleWeasel/modules/dictionary_cache_servicable.rb +26 -0
- data/lib/LittleWeasel/modules/dictionary_cache_validatable.rb +18 -0
- data/lib/LittleWeasel/modules/dictionary_creator_servicable.rb +27 -0
- data/lib/LittleWeasel/modules/dictionary_file_loader.rb +67 -0
- data/lib/LittleWeasel/modules/dictionary_key_validatable.rb +17 -0
- data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
- data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
- data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +15 -0
- data/lib/LittleWeasel/modules/dictionary_source_validatable.rb +15 -0
- data/lib/LittleWeasel/modules/dictionary_sourceable.rb +86 -0
- data/lib/LittleWeasel/modules/dictionary_validatable.rb +18 -0
- data/lib/LittleWeasel/modules/language.rb +24 -0
- data/lib/LittleWeasel/modules/language_validatable.rb +14 -0
- data/lib/LittleWeasel/modules/locale.rb +23 -0
- data/lib/LittleWeasel/modules/order_validatable.rb +16 -0
- data/lib/LittleWeasel/modules/orderable.rb +17 -0
- data/lib/LittleWeasel/modules/region.rb +24 -0
- data/lib/LittleWeasel/modules/region_validatable.rb +14 -0
- data/lib/LittleWeasel/modules/tag_validatable.rb +14 -0
- data/lib/LittleWeasel/modules/taggable.rb +31 -0
- data/lib/LittleWeasel/modules/word_results_validatable.rb +28 -0
- data/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor.rb +22 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_word.rb +29 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +56 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +59 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +28 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +123 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor_managable.rb +114 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor_validatable.rb +40 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessors_validatable.rb +24 -0
- data/lib/LittleWeasel/services/dictionary_cache_service.rb +211 -0
- data/lib/LittleWeasel/services/dictionary_creator_service.rb +94 -0
- data/lib/LittleWeasel/services/dictionary_file_loader_service.rb +37 -0
- data/lib/LittleWeasel/services/dictionary_killer_service.rb +35 -0
- data/lib/LittleWeasel/services/dictionary_metadata_service.rb +116 -0
- data/lib/LittleWeasel/services/invalid_words_service.rb +59 -0
- data/lib/LittleWeasel/version.rb +3 -1
- data/lib/LittleWeasel/word_results.rb +146 -0
- data/lib/LittleWeasel.rb +72 -186
- data/spec/factories/dictionary.rb +43 -0
- data/spec/factories/dictionary_cache_service.rb +95 -0
- data/spec/factories/dictionary_creator_service.rb +16 -0
- data/spec/factories/dictionary_file_loader_service.rb +13 -0
- data/spec/factories/dictionary_hash.rb +39 -0
- data/spec/factories/dictionary_key.rb +14 -0
- data/spec/factories/dictionary_killer_service.rb +14 -0
- data/spec/factories/dictionary_manager.rb +10 -0
- data/spec/factories/dictionary_metadata.rb +16 -0
- data/spec/factories/dictionary_metadata_service.rb +16 -0
- data/spec/factories/numeric_filter.rb +12 -0
- data/spec/factories/preprocessed_word.rb +16 -0
- data/spec/factories/preprocessed_words.rb +41 -0
- data/spec/factories/single_character_word_filter.rb +12 -0
- data/spec/factories/word_results.rb +16 -0
- data/spec/lib/LittleWeasel/block_results_spec.rb +248 -0
- data/spec/lib/LittleWeasel/configure_spec.rb +74 -0
- data/spec/lib/LittleWeasel/dictionary_key_spec.rb +118 -0
- data/spec/lib/LittleWeasel/dictionary_manager_spec.rb +166 -0
- data/spec/lib/LittleWeasel/dictionary_spec.rb +289 -0
- data/spec/lib/LittleWeasel/filters/en_us/currency_filter_spec.rb +80 -0
- data/spec/lib/LittleWeasel/filters/en_us/numeric_filter_spec.rb +66 -0
- data/spec/lib/LittleWeasel/filters/en_us/single_character_word_filter_spec.rb +58 -0
- data/spec/lib/LittleWeasel/filters/word_filter_managable_spec.rb +180 -0
- data/spec/lib/LittleWeasel/filters/word_filter_spec.rb +151 -0
- data/spec/lib/LittleWeasel/filters/word_filter_validatable_spec.rb +94 -0
- data/spec/lib/LittleWeasel/filters/word_filters_validatable_spec.rb +48 -0
- data/spec/lib/LittleWeasel/integraton_tests/dictionary_integration_spec.rb +201 -0
- data/spec/lib/LittleWeasel/metadata/dictionary_creator_servicable_spec.rb +54 -0
- data/spec/lib/LittleWeasel/metadata/dictionary_metadata_spec.rb +209 -0
- data/spec/lib/LittleWeasel/metadata/invalid_words_metadata_spec.rb +155 -0
- data/spec/lib/LittleWeasel/metadata/metadata_observerable_spec.rb +31 -0
- data/spec/lib/LittleWeasel/metadata/metadatable_spec.rb +35 -0
- data/spec/lib/LittleWeasel/modules/class_name_to_symbol_spec.rb +21 -0
- data/spec/lib/LittleWeasel/modules/dictionary_file_loader_spec.rb +125 -0
- data/spec/lib/LittleWeasel/modules/dictionary_sourceable_spec.rb +81 -0
- data/spec/lib/LittleWeasel/modules/language_spec.rb +112 -0
- data/spec/lib/LittleWeasel/modules/locale_spec.rb +95 -0
- data/spec/lib/LittleWeasel/modules/region_spec.rb +112 -0
- data/spec/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor_spec.rb +34 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_spec.rb +105 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_validatable_spec.rb +143 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_spec.rb +77 -0
- data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_validatable_spec.rb +58 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_managable_spec.rb +242 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +218 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_validatable_spec.rb +109 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessors_validatable_spec.rb +49 -0
- data/spec/lib/LittleWeasel/services/dictionary_cache_service_spec.rb +444 -0
- data/spec/lib/LittleWeasel/services/dictionary_creator_service_spec.rb +119 -0
- data/spec/lib/LittleWeasel/services/dictionary_file_loader_service_spec.rb +71 -0
- data/spec/lib/LittleWeasel/services/dictionary_metadata_service_spec.rb +279 -0
- data/spec/lib/LittleWeasel/word_results_spec.rb +275 -0
- data/spec/lib/LittleWeasel/workflow/workflow_spec.rb +20 -0
- data/spec/spec_helper.rb +117 -6
- data/spec/support/factory_bot.rb +15 -0
- data/spec/support/file_helpers.rb +46 -0
- data/spec/support/files/empty-dictionary.txt +0 -0
- data/{lib/dictionary → spec/support/files/en-US-big.txt} +262156 -31488
- data/spec/support/files/en-US-tagged.txt +26 -0
- data/spec/support/files/en-US.txt +26 -0
- data/spec/support/files/en.txt +26 -0
- data/spec/support/files/es-ES.txt +27 -0
- data/spec/support/files/es.txt +27 -0
- data/spec/support/general_helpers.rb +68 -0
- data/spec/support/shared_contexts.rb +107 -0
- data/spec/support/shared_examples.rb +105 -0
- metadata +418 -70
- data/spec/checker/checker_spec.rb +0 -286
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe 'Dictionary integration', type: :integration do
|
|
6
|
+
include_context 'dictionary keys'
|
|
7
|
+
include_context 'mock word preprocessors'
|
|
8
|
+
|
|
9
|
+
subject { create(:dictionary_manager) }
|
|
10
|
+
|
|
11
|
+
before(:each) { LittleWeasel.configure { |config| config.reset } }
|
|
12
|
+
|
|
13
|
+
let(:dictionary) do
|
|
14
|
+
subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: dictionary_file_path,
|
|
15
|
+
word_filters: word_filters, word_preprocessors: word_preprocessors)
|
|
16
|
+
end
|
|
17
|
+
let(:dictionary_key) { dictionary_key_for(language: :en, region: :us) }
|
|
18
|
+
let(:dictionary_cache) { subject.dictionary_cache }
|
|
19
|
+
let(:dictionary_metadata) { subject.dictionary_metadata }
|
|
20
|
+
let(:dictionary_file_path) { dictionary_path_for(file_name: dictionary_key.key) }
|
|
21
|
+
let(:dictionary_words) { dictionary_words_for(dictionary_file_path: dictionary_file_path) }
|
|
22
|
+
let(:word_filters) {}
|
|
23
|
+
let(:word_preprocessors) {}
|
|
24
|
+
|
|
25
|
+
#word_results
|
|
26
|
+
describe '#word_results' do
|
|
27
|
+
describe 'when using word filters' do
|
|
28
|
+
let(:word_filters) { [LittleWeasel::Filters::EnUs::NumericFilter.new] }
|
|
29
|
+
let(:number) { 1_000.to_s }
|
|
30
|
+
|
|
31
|
+
context 'with word filters turned on' do
|
|
32
|
+
let(:word_results) { dictionary.word_results(number) }
|
|
33
|
+
|
|
34
|
+
it '#success? returns true' do
|
|
35
|
+
expect(word_results.success?).to eq true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it '#filter_match? returns true' do
|
|
39
|
+
expect(word_results.filter_match?).to eq true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it '#filters_matched returns the filter(s) that were matched' do
|
|
43
|
+
expect(word_results.filters_matched).to eq [:numeric_filter]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it '#word_valid? returns false' do
|
|
47
|
+
expect(word_results.word_valid?).to eq false
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it '#original_word returns the original word' do
|
|
51
|
+
expect(word_results.preprocessed_word_or_original_word).to eq number
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it '#preprocessed_word return nil because no word preprocessors were applied' do
|
|
55
|
+
expect(word_results.preprocessed_word).to be_nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it '#preprocessed_word_or_original_word returns the original word' do
|
|
59
|
+
expect(word_results.preprocessed_word_or_original_word).to eq number
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it '#word_cached? returns false if the word is not in the dictionary' do
|
|
63
|
+
expect(word_results.word_cached?).to eq false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it '#word_cached? returns true 2nd-nth time the word was searched if invalid words are being cached by any metadata processing' do
|
|
67
|
+
dictionary.word_results(number)
|
|
68
|
+
expect(word_results.word_cached?).to eq true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'with filters turned off' do
|
|
73
|
+
before do
|
|
74
|
+
dictionary.filters_on = false
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
let(:word_results) { dictionary.word_results(number) }
|
|
78
|
+
|
|
79
|
+
it '#success? returns false' do
|
|
80
|
+
expect(word_results.success?).to eq false
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it '#filter_match? returns false' do
|
|
84
|
+
expect(word_results.filter_match?).to eq false
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it '#filters_matched returns an empty Array' do
|
|
88
|
+
expect(word_results.filters_matched).to eq []
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it '#word_valid? returns false' do
|
|
92
|
+
expect(word_results.word_valid?).to eq false
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it '#original_word returns the original word' do
|
|
96
|
+
expect(word_results.original_word).to eq number
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it '#preprocessed_word return nil because no word preprocessors were applied' do
|
|
100
|
+
expect(word_results.preprocessed_word).to be_nil
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it '#preprocessed_word_or_original_word returns the original word' do
|
|
104
|
+
expect(word_results.preprocessed_word_or_original_word).to eq number
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it '#word_cached? returns false if the word is not in the dictionary' do
|
|
108
|
+
expect(word_results.word_cached?).to eq false
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it '#word_cached? returns true 2nd-nth time the word was searched if invalid words are being cached by any metadata processing' do
|
|
112
|
+
dictionary.word_results(number)
|
|
113
|
+
expect(word_results.word_cached?).to eq true
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe 'when using word preprocessors' do
|
|
119
|
+
let(:word_preprocessors) { [DowncaseWordPreprocessor.new(order: 0)] }
|
|
120
|
+
let(:word) { 'ApPlE' }
|
|
121
|
+
let(:word_results) { dictionary.word_results(word) }
|
|
122
|
+
|
|
123
|
+
context 'with preprocessors turned on' do
|
|
124
|
+
it '#success? returns true' do
|
|
125
|
+
expect(word_results.success?).to eq true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it '#filter_match? returns false' do
|
|
129
|
+
expect(word_results.filter_match?).to eq false
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it '#filters_matched returns the filter(s) that were matched' do
|
|
133
|
+
expect(word_results.filters_matched).to eq []
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it '#word_valid? returns true' do
|
|
137
|
+
expect(word_results.word_valid?).to eq true
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it '#original_word returns the original word' do
|
|
141
|
+
expect(word_results.original_word).to eq word
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it '#preprocessed_word returns the preprocessed word' do
|
|
145
|
+
expect(word_results.preprocessed_word).to eq word.downcase
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it '#preprocessed_word_or_original_word returns the preprocessed word' do
|
|
149
|
+
expect(word_results.preprocessed_word_or_original_word).to eq word.downcase
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it '#word_cached? returns true if the word is in the dictionary' do
|
|
153
|
+
expect(word_results.word_cached?).to eq true
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context 'with preprocessors turned off' do
|
|
158
|
+
before do
|
|
159
|
+
dictionary.preprocessors_on = false
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it '#success? returns false' do
|
|
163
|
+
expect(word_results.success?).to eq false
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it '#filter_match? returns false' do
|
|
167
|
+
expect(word_results.filter_match?).to eq false
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it '#filters_matched returns the filter(s) that were matched' do
|
|
171
|
+
expect(word_results.filters_matched).to eq []
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it '#word_valid? returns false' do
|
|
175
|
+
expect(word_results.word_valid?).to eq false
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it '#original_word returns the original word' do
|
|
179
|
+
expect(word_results.original_word).to eq word
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it '#preprocessed_word returns nil' do
|
|
183
|
+
expect(word_results.preprocessed_word).to be_nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it '#preprocessed_word_or_original_word returns the original word' do
|
|
187
|
+
expect(word_results.preprocessed_word_or_original_word).to eq word
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it '#word_cached? returns false if the word is not in the dictionary' do
|
|
191
|
+
expect(word_results.word_cached?).to eq false
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
it '#word_cached? returns true 2nd-nth time the word was searched if invalid words are being cached by any metadata processing' do
|
|
195
|
+
dictionary.word_results(word)
|
|
196
|
+
expect(word_results.word_cached?).to eq true
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Modules::DictionaryCreatorServicable, type: :module do
|
|
6
|
+
include_context 'dictionary keys'
|
|
7
|
+
|
|
8
|
+
DictionaryCreatorServicable = described_class
|
|
9
|
+
|
|
10
|
+
class SubjectMock
|
|
11
|
+
include DictionaryCreatorServicable
|
|
12
|
+
include LittleWeasel::Filters::WordFilterable
|
|
13
|
+
include LittleWeasel::Modules::DictionaryKeyable
|
|
14
|
+
include LittleWeasel::Modules::DictionaryMetadataServicable
|
|
15
|
+
|
|
16
|
+
def initialize(dictionary_key:, dictionary_cache:, dictionary_metadata:, word_filters:)
|
|
17
|
+
self.dictionary_key = dictionary_key
|
|
18
|
+
self.dictionary_cache = dictionary_cache
|
|
19
|
+
self.dictionary_metadata = dictionary_metadata
|
|
20
|
+
self.word_filters = word_filters
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
subject { SubjectMock.new(dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata, word_filters: word_filters) }
|
|
25
|
+
|
|
26
|
+
let(:en_us_dictionary_key) { dictionary_key_for(language: :en, region: :us) }
|
|
27
|
+
let(:dictionary_key) { en_us_dictionary_key }
|
|
28
|
+
let(:key) { dictionary_key.key }
|
|
29
|
+
let(:file) { dictionary_path_for(file_name: key) }
|
|
30
|
+
let(:dictionary_cache) { {} }
|
|
31
|
+
let(:dictionary_metadata) { {} }
|
|
32
|
+
let(:word_filters) {}
|
|
33
|
+
|
|
34
|
+
#attributes
|
|
35
|
+
describe 'attributes' do
|
|
36
|
+
it 'responds to the correct attributes' do
|
|
37
|
+
expect(subject).to respond_to(
|
|
38
|
+
:dictionary_key,
|
|
39
|
+
:dictionary_cache,
|
|
40
|
+
:word_filters)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#dictionary_creator_service
|
|
45
|
+
describe '#dictionary_creator_service' do
|
|
46
|
+
it 'responds to #dictionary_creator_service' do
|
|
47
|
+
expect(subject).to respond_to(:dictionary_creator_service)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'returns a Services::DictionaryCreatorService object' do
|
|
51
|
+
expect(subject.dictionary_creator_service).to be_kind_of LittleWeasel::Services::DictionaryCreatorService
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Metadata::DictionaryMetadata do
|
|
6
|
+
subject { create(:dictionary_metadata, dictionary_words: dictionary_words, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata) }
|
|
7
|
+
|
|
8
|
+
let!(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: true, load: true) }
|
|
9
|
+
let!(:dictionary_metadata_service) { create(:dictionary_metadata_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata) }
|
|
10
|
+
let(:dictionary_words) { create(:dictionary_hash) }
|
|
11
|
+
let(:dictionary_key) { create(:dictionary_key) }
|
|
12
|
+
let(:dictionary_cache) { {} }
|
|
13
|
+
let(:dictionary_metadata) { {} }
|
|
14
|
+
let(:invalid_words_metadata_key) { invalid_words_metadata_class.metadata_key }
|
|
15
|
+
let(:invalid_words_metadata_class) { LittleWeasel::Metadata::InvalidWordsMetadata }
|
|
16
|
+
|
|
17
|
+
#.new
|
|
18
|
+
describe '#.new' do
|
|
19
|
+
context 'with valid arguments' do
|
|
20
|
+
it 'instantiates the object' do
|
|
21
|
+
expect { subject }.to_not raise_error
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'with invalid arguments' do
|
|
26
|
+
context 'when dictionary_words is nil' do
|
|
27
|
+
# Note: do not use the factory for this spec becasue
|
|
28
|
+
# it creates a dictionary if a nil dictionay is passed
|
|
29
|
+
# so the test will never pass if using the factory.
|
|
30
|
+
subject { described_class.new(dictionary_words: dictionary_words, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata) }
|
|
31
|
+
|
|
32
|
+
let(:dictionary_words) {}
|
|
33
|
+
|
|
34
|
+
it 'raises an error' do
|
|
35
|
+
expect { subject }.to raise_error(/Argument dictionary_words is not a Hash/)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when dictionary_words is not a Hash' do
|
|
40
|
+
let(:dictionary_words) { %w(I am a bad dictionary) }
|
|
41
|
+
|
|
42
|
+
it 'raises an error' do
|
|
43
|
+
expect { subject }.to raise_error(/Argument dictionary_words is not a Hash/)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
#[]
|
|
50
|
+
describe '#[]' do
|
|
51
|
+
context 'when passing a valid metadata_key' do
|
|
52
|
+
context 'when it is a key that points to a valid metadata observer' do
|
|
53
|
+
before do
|
|
54
|
+
subject.add_observers
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'returns the metadata observer object' do
|
|
58
|
+
expect(subject[invalid_words_metadata_key]).to be_kind_of invalid_words_metadata_class
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
context 'when it is a key that DOES NOT point to a valid metadata observer' do
|
|
63
|
+
it 'returns nil' do
|
|
64
|
+
expect(subject[invalid_words_metadata_key]).to be_nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'when passing an INVALID metadata_key' do
|
|
70
|
+
it 'returns nil' do
|
|
71
|
+
expect(subject[:bad_metadata_key]).to be_nil
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#init
|
|
77
|
+
describe '#init' do
|
|
78
|
+
context 'when there are observers attached' do
|
|
79
|
+
before do
|
|
80
|
+
subject.add_observers
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context 'when metadata is in the dictionary cache' do
|
|
84
|
+
it 'observers are notified to init' do
|
|
85
|
+
# Sanity check.
|
|
86
|
+
expect(subject.count_observers).to eq 1
|
|
87
|
+
expect(subject.observers[invalid_words_metadata_key]).to receive(:init)
|
|
88
|
+
subject.init
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'when there are NO observers attached' do
|
|
94
|
+
it 'observers are NOT notified to init' do
|
|
95
|
+
# Sanity check.
|
|
96
|
+
expect(subject.count_observers).to eq 0
|
|
97
|
+
expect(subject.observers[invalid_words_metadata_key]).to_not receive(:init)
|
|
98
|
+
subject.init
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'when dictionary metadata is already in the dictionary cache' do
|
|
103
|
+
it 'inits the metadata with what is currently in the dictionary cache' do
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#refresh
|
|
109
|
+
describe '#refresh' do
|
|
110
|
+
context 'when there are observers attached' do
|
|
111
|
+
before do
|
|
112
|
+
subject.add_observers
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'observers are notified to refresh' do
|
|
116
|
+
# Sanity check.
|
|
117
|
+
expect(subject.count_observers).to eq 1
|
|
118
|
+
expect(subject.observers[invalid_words_metadata_key]).to receive(:refresh)
|
|
119
|
+
subject.refresh
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context 'when there are NO observers attached' do
|
|
124
|
+
it 'observers are NOT notified to refresh' do
|
|
125
|
+
# Sanity check.
|
|
126
|
+
expect(subject.count_observers).to eq 0
|
|
127
|
+
expect(subject.observers[invalid_words_metadata_key]).to_not receive(:refresh)
|
|
128
|
+
subject.refresh
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context 'when dictionary metadata is already in the dictionary cache' do
|
|
133
|
+
it 'refreshes the metadata with what is currently in the dictionary cache' do
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#delete_observer
|
|
139
|
+
describe '#delete_observer' do
|
|
140
|
+
context 'when a valid observer object is passed' do
|
|
141
|
+
before do
|
|
142
|
+
subject.add_observers
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
let(:observer) { subject.observers.values.first }
|
|
146
|
+
|
|
147
|
+
it 'the observer is removed from the #observers list' do
|
|
148
|
+
expect { subject.delete_observer(observer) }
|
|
149
|
+
.to change { subject.observers.count }
|
|
150
|
+
.from(1)
|
|
151
|
+
.to(0)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
context 'when an INVALID observer object is passed' do
|
|
156
|
+
let(:bad_observer) { :bad_observer }
|
|
157
|
+
|
|
158
|
+
it 'raises an error' do
|
|
159
|
+
expect { subject.delete_observer(bad_observer) }.to raise_error 'Argument metadata_observable is not a ' \
|
|
160
|
+
"Metadata::MetadataObserverable object: #{bad_observer.class}"
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
#add_observers
|
|
166
|
+
describe '#add_observers' do
|
|
167
|
+
it 'returns the same object that was called' do
|
|
168
|
+
expect(subject.add_observers).to be subject
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context 'when a metadata object is in a state to observe' do
|
|
172
|
+
it 'added as an observer' do
|
|
173
|
+
expect(subject.add_observers.count_observers).to eq 1
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context 'when #add_observers is called more than once' do
|
|
177
|
+
context 'when argument force is true (force: true)' do
|
|
178
|
+
before do
|
|
179
|
+
subject.add_observers
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'reinstantiates and replaces the observers' do
|
|
183
|
+
expect(subject.add_observers(force: true).count_observers).to eq 1
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
context 'when argument force is false (force: false)' do
|
|
188
|
+
before do
|
|
189
|
+
subject.add_observers
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'raises an error' do
|
|
193
|
+
expect { subject.add_observers }.to raise_error 'Observers have already been added; use #add_observers(force: true) instead'
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context 'when a metadata object is NOT in a state to observe' do
|
|
200
|
+
before do
|
|
201
|
+
allow(LittleWeasel::Metadata::InvalidWordsMetadata).to receive(:observe?).and_return(false)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'NOT added as an observer' do
|
|
205
|
+
expect(subject.add_observers.count_observers).to eq 0
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'observer'
|
|
5
|
+
|
|
6
|
+
RSpec.describe LittleWeasel::Metadata::InvalidWordsMetadata do
|
|
7
|
+
subject do
|
|
8
|
+
dictionary.dictionary_metadata_object[:invalid_words_metadata]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:dictionary) { dictionary_manager.create_dictionary_from_file(dictionary_key: dictionary_key, file: file) }
|
|
12
|
+
let(:dictionary_manager) { create(:dictionary_manager) }
|
|
13
|
+
|
|
14
|
+
let(:dictionary_key) { create(:dictionary_key, language: language, region: region, tag: tag) }
|
|
15
|
+
let(:language) { :en }
|
|
16
|
+
let(:region) { :us }
|
|
17
|
+
let(:tag) {}
|
|
18
|
+
let(:dictionary_cache) { {} }
|
|
19
|
+
let(:dictionary_metadata) { {} }
|
|
20
|
+
let(:file) { dictionary_path_for file_name: dictionary_key.key }
|
|
21
|
+
|
|
22
|
+
let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache) }
|
|
23
|
+
let(:invalid_words_metadata) { described_class.new(dictionary_metadata_object: dictionary_metadata_object, dictionary_words: dictionary_words, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata) }
|
|
24
|
+
let(:dictionary_metadata_object) do
|
|
25
|
+
Class.new do
|
|
26
|
+
include Observable
|
|
27
|
+
end.new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:configuration) { LittleWeasel.configuration }
|
|
31
|
+
|
|
32
|
+
#new
|
|
33
|
+
describe '#new' do
|
|
34
|
+
context 'with invalid arguments' do
|
|
35
|
+
subject { invalid_words_metadata }
|
|
36
|
+
|
|
37
|
+
before do
|
|
38
|
+
dictionary_cache_service.add_dictionary_source(dictionary_source: file)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'with invalid dictionary metadata object' do
|
|
42
|
+
let(:dictionary_words) { { 'a' => true, 'b' => true } }
|
|
43
|
+
let(:dictionary_metadata_object) { :wrong_type }
|
|
44
|
+
|
|
45
|
+
it 'raises an error' do
|
|
46
|
+
expect { subject }.to raise_error "Argument dictionary_metadata_object is not an Observable: #{dictionary_metadata_object.class}."
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'with invalid dictionary metadata' do
|
|
51
|
+
let(:dictionary_words) { { 'a' => true, 'b' => true } }
|
|
52
|
+
let(:dictionary_metadata) { :wrong_type }
|
|
53
|
+
|
|
54
|
+
it 'raises an error' do
|
|
55
|
+
expect { subject }.to raise_error "Argument dictionary_metadata is not a valid Hash object: #{dictionary_metadata.class}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'with an invalid dictionary' do
|
|
60
|
+
let(:dictionary_words) { :wrong_type }
|
|
61
|
+
|
|
62
|
+
it 'raises an error' do
|
|
63
|
+
expect { subject }.to raise_error "Argument dictionary_words is not a Hash: #{dictionary_words.class}."
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context 'with a valid arguments' do
|
|
69
|
+
before do
|
|
70
|
+
subject.word_search params: { word_results: word_results1 }
|
|
71
|
+
subject.word_search params: { word_results: word_results2 }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
let(:word_results1) { create(:word_results, original_word: 'badword1') }
|
|
75
|
+
let(:word_results2) { create(:word_results, original_word: 'badword2') }
|
|
76
|
+
|
|
77
|
+
it 'instantiates without error' do
|
|
78
|
+
expect { subject }.to_not raise_error
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'initializes the necessary object attributes' do
|
|
82
|
+
expect(subject.on?).to eq true
|
|
83
|
+
expect(subject.off?).to eq false
|
|
84
|
+
expect(subject.value).to eq configuration.max_invalid_words_bytesize
|
|
85
|
+
expect(subject.value_exceeded?).to eq false
|
|
86
|
+
expect(subject.current_invalid_word_bytesize).to eq 16
|
|
87
|
+
expect(subject.cache_invalid_words?).to eq true
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
context 'with an invalid dictionary words Hash' do
|
|
92
|
+
subject { invalid_words_metadata }
|
|
93
|
+
|
|
94
|
+
context 'when nil' do
|
|
95
|
+
let(:dictionary_words) {}
|
|
96
|
+
|
|
97
|
+
it 'raises an error' do
|
|
98
|
+
expect { subject }.to raise_error ArgumentError
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'when not a Hash' do
|
|
103
|
+
let(:dictionary_words) { :not_an_array }
|
|
104
|
+
|
|
105
|
+
it 'raises an error' do
|
|
106
|
+
expect { subject }.to raise_error ArgumentError
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
#refresh
|
|
113
|
+
describe '#refresh' do
|
|
114
|
+
it 'the metadata is refreshed' do
|
|
115
|
+
expect(subject.current_invalid_word_bytesize).to eq 0
|
|
116
|
+
expect do
|
|
117
|
+
dictionary.word_results('badword')
|
|
118
|
+
subject.refresh
|
|
119
|
+
end.to change { subject.current_invalid_word_bytesize }
|
|
120
|
+
.from(0).to(7)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#init
|
|
125
|
+
describe '#init' do
|
|
126
|
+
it 'the metadata is initialized' do
|
|
127
|
+
expect do
|
|
128
|
+
subject.dictionary_metadata_object.dictionary_words['not-found'] = false
|
|
129
|
+
subject.init
|
|
130
|
+
end.to change { subject.current_invalid_word_bytesize }
|
|
131
|
+
.from(0).to(9)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
#Update
|
|
136
|
+
describe '#update' do
|
|
137
|
+
context 'with an action NOT on the whitelist' do
|
|
138
|
+
let(:action) { :bad_action! }
|
|
139
|
+
let(:params) { :params }
|
|
140
|
+
|
|
141
|
+
it 'raises an error' do
|
|
142
|
+
expect { subject.update(action, params) }.to raise_error "Argument action is not in the actions_whitelist: #{action}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context 'with an action on the whitelist' do
|
|
147
|
+
it 'carries out the requested action' do
|
|
148
|
+
expect do
|
|
149
|
+
dictionary.word_results 'not-found'
|
|
150
|
+
end.to change { subject.current_invalid_word_bytesize }
|
|
151
|
+
.from(0).to(9)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Metadata::MetadataObserverable, type: :module do
|
|
6
|
+
MetadataObserverable = described_class
|
|
7
|
+
|
|
8
|
+
subject do
|
|
9
|
+
Class.new do
|
|
10
|
+
include MetadataObserverable
|
|
11
|
+
end.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#observe?' do
|
|
15
|
+
it 'returns false by default' do
|
|
16
|
+
expect(subject.observe?).to eq false
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '#update' do
|
|
21
|
+
it 'raises an error if not overridden' do
|
|
22
|
+
expect { subject.update :action, args: :args }.to raise_error LittleWeasel::Errors::MustOverrideError
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#actions_whitelist' do
|
|
27
|
+
it 'returns an Array with :init and :refresh Symbols by default' do
|
|
28
|
+
expect(subject.actions_whitelist).to eq %i[init refresh]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Metadata::Metadatable, type: :module do
|
|
6
|
+
Metadatable = described_class
|
|
7
|
+
|
|
8
|
+
subject do
|
|
9
|
+
Class.new do
|
|
10
|
+
include Metadatable
|
|
11
|
+
|
|
12
|
+
def update_dictionary_metadata_test
|
|
13
|
+
update_dictionary_metadata value: :value
|
|
14
|
+
end
|
|
15
|
+
end.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#init' do
|
|
19
|
+
it 'raises an error if not overridden' do
|
|
20
|
+
expect { subject.init }.to raise_error LittleWeasel::Errors::MustOverrideError
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#refresh' do
|
|
25
|
+
it 'raises an error if not overridden' do
|
|
26
|
+
expect { subject.refresh }.to raise_error LittleWeasel::Errors::MustOverrideError
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe '#update_dictionary_metadata' do
|
|
31
|
+
it 'raises an error if not overridden' do
|
|
32
|
+
expect { subject.update_dictionary_metadata_test }.to raise_error LittleWeasel::Errors::MustOverrideError
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|