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.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- 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 +22 -1
- data/Gemfile +3 -1
- 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 +5 -184
- 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 +378 -38
- data/spec/checker/checker_spec.rb +0 -286
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::DictionaryManager do
|
|
6
|
+
include_context 'dictionary keys'
|
|
7
|
+
|
|
8
|
+
subject { create(:dictionary_manager) }
|
|
9
|
+
|
|
10
|
+
let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache)}
|
|
11
|
+
let(:dictionary_metadata_service) { create(:dictionary_metadata_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata)}
|
|
12
|
+
let(:dictionary_key) { create(:dictionary_key, language: language, region: region, tag: tag) }
|
|
13
|
+
let(:dictionary_cache) { subject.dictionary_cache }
|
|
14
|
+
let(:dictionary_metadata) { subject.dictionary_metadata }
|
|
15
|
+
|
|
16
|
+
let(:language) { :en }
|
|
17
|
+
let(:region) { :us }
|
|
18
|
+
let(:tag) {}
|
|
19
|
+
let(:file) { dictionary_path_for(file_name: dictionary_key.key) }
|
|
20
|
+
|
|
21
|
+
let(:metadata_key) do
|
|
22
|
+
dictionary_cache_service.dictionary_object.dictionary_metadata_object.observers.keys.first
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
before(:each) do
|
|
26
|
+
subject.init
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#.new
|
|
30
|
+
describe '.new' do
|
|
31
|
+
it 'does not raise an error' do
|
|
32
|
+
expect { subject }.not_to raise_error
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
#dictionary_exist?
|
|
37
|
+
describe '#dictionary_exist?' do
|
|
38
|
+
let!(:expected_dictionary_object) do
|
|
39
|
+
subject.create_dictionary_from_memory(dictionary_key: dictionary_key,
|
|
40
|
+
dictionary_words: %w(My dictionary words) )
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'when the dictionary exists' do
|
|
44
|
+
it 'returns true' do
|
|
45
|
+
expect(subject.dictionary_exist? dictionary_key: dictionary_key)
|
|
46
|
+
.to eq true
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context 'when the dictionary DOES NOT exist' do
|
|
51
|
+
let(:en_gb_dictionary_key) { dictionary_key_for(language: :en, region: :gb) }
|
|
52
|
+
|
|
53
|
+
it 'returns false' do
|
|
54
|
+
expect(subject.dictionary_exist? dictionary_key: en_gb_dictionary_key)
|
|
55
|
+
.to eq false
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#dictionary_for
|
|
61
|
+
describe '#dictionary_for' do
|
|
62
|
+
let!(:expected_dictionary_object) do
|
|
63
|
+
subject.create_dictionary_from_memory(dictionary_key: dictionary_key,
|
|
64
|
+
dictionary_words: %w(My dictionary words) )
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'when the dictionary exists' do
|
|
68
|
+
it 'returns the dictionary object' do
|
|
69
|
+
expect(subject.dictionary_for dictionary_key: dictionary_key)
|
|
70
|
+
.to be expected_dictionary_object
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context 'when the dictionary DOES NOT exist' do
|
|
75
|
+
let(:en_gb_dictionary_key) { dictionary_key_for(language: :en, region: :gb) }
|
|
76
|
+
|
|
77
|
+
it 'raises an error' do
|
|
78
|
+
expect { subject.dictionary_for dictionary_key: en_gb_dictionary_key }
|
|
79
|
+
.to raise_error("The dictionary object associated with argument key '#{en_gb_dictionary_key.key}' is not in the cache.")
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
#create_dictionary_from_file
|
|
85
|
+
describe '#create_dictionary_from_file' do
|
|
86
|
+
context 'when the dictionary DOES NOT exist' do
|
|
87
|
+
it 'creates a dictionary and returns a dictionary object' do
|
|
88
|
+
expect(subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)).to be_kind_of LittleWeasel::Dictionary
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'when the dictionary already exists' do
|
|
93
|
+
before do
|
|
94
|
+
subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'raises an error' do
|
|
98
|
+
expect { subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file) }
|
|
99
|
+
.to raise_error("The dictionary source associated with key '#{dictionary_key.key}' already exists.")
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#create_dictionary_from_memory
|
|
105
|
+
describe '#create_dictionary_from_memory' do
|
|
106
|
+
let(:dictionary_words) { dictionary_words_for(dictionary_file_path: file) }
|
|
107
|
+
|
|
108
|
+
context 'when the dictionary reference does not exist and the dictionary is not cached' do
|
|
109
|
+
it 'adds a dictionary reference caches the dictionary and returns a dictionary object' do
|
|
110
|
+
expect(subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words)).to be_kind_of LittleWeasel::Dictionary
|
|
111
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq true
|
|
112
|
+
expect(dictionary_cache_service.dictionary_object?).to eq true
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'when the dictionary reference exists' do
|
|
117
|
+
before do
|
|
118
|
+
subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'raises an error' do
|
|
122
|
+
expect { subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words) }
|
|
123
|
+
.to raise_error "The dictionary source associated with key '#{dictionary_key.key}' already exists."
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
#kill
|
|
129
|
+
describe '#kill_dictionary' do
|
|
130
|
+
context 'dictionaries created from files' do
|
|
131
|
+
before do
|
|
132
|
+
subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'removes the dictionary, file source reference and metadata from the dictionary cache' do
|
|
136
|
+
metadata_key # Capture this before we unload the dictionary
|
|
137
|
+
subject.kill_dictionary(dictionary_key: dictionary_key)
|
|
138
|
+
expect(dictionary_cache_service.dictionary_exist?).to eq false
|
|
139
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq false
|
|
140
|
+
expect(dictionary_metadata_service.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'returns the dictionary manager instance' do
|
|
144
|
+
expect(subject.kill_dictionary(dictionary_key: dictionary_key)).to eq subject
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context 'dictionaries created from memory' do
|
|
149
|
+
before do
|
|
150
|
+
subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: %w(Abel Cain Deborah Elijah))
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'removes the dictionary, memory source reference and metadata from the dictionary cache' do
|
|
154
|
+
metadata_key # Capture this before we unload the dictionary
|
|
155
|
+
subject.kill_dictionary(dictionary_key: dictionary_key)
|
|
156
|
+
expect(dictionary_cache_service.dictionary_exist?).to eq false
|
|
157
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq false
|
|
158
|
+
expect(dictionary_metadata_service.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it 'returns the dictionary manager instance' do
|
|
162
|
+
expect(subject.kill_dictionary(dictionary_key: dictionary_key)).to eq subject
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Dictionary do
|
|
6
|
+
include_context 'dictionary keys'
|
|
7
|
+
include_context 'mock word filters'
|
|
8
|
+
|
|
9
|
+
DictionaryResultsHelpers = Support::GeneralHelpers::DictionaryResultsHelpers
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
subject { create(:dictionary, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_words: dictionary_words, word_filters: word_filters) }
|
|
13
|
+
|
|
14
|
+
before(:each) { LittleWeasel.configure { |config| config.reset } }
|
|
15
|
+
before { dictionary_cache_service }
|
|
16
|
+
|
|
17
|
+
let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: dictionary_key.key) }
|
|
18
|
+
let(:dictionary_key) { dictionary_key_for(language: :en, region: :us, tag: :big) }
|
|
19
|
+
let(:dictionary_cache) { {} }
|
|
20
|
+
let(:dictionary_metadata) { {} }
|
|
21
|
+
let(:dictionary_file_path) { dictionary_path_for(file_name: dictionary_key.key) }
|
|
22
|
+
let(:dictionary_words) { dictionary_words_for(dictionary_file_path: dictionary_file_path) }
|
|
23
|
+
let(:word_filters) {}
|
|
24
|
+
|
|
25
|
+
def block_results_include?(block_results, word)
|
|
26
|
+
word_results = block_results.word_results.find do |word_results|
|
|
27
|
+
word_results.original_word == word
|
|
28
|
+
end
|
|
29
|
+
[word_results.present?, word_results&.word_valid]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#.new
|
|
33
|
+
describe '.new' do
|
|
34
|
+
context 'with a valid dictionary words Array' do
|
|
35
|
+
it 'instantiates without error' do
|
|
36
|
+
expect { subject }.to_not raise_error
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'with an invalid dictionary words Array' do
|
|
41
|
+
context 'when nil' do
|
|
42
|
+
let(:dictionary_words) {}
|
|
43
|
+
|
|
44
|
+
it 'raises an error' do
|
|
45
|
+
expect { subject }.to raise_error ArgumentError
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context 'when not an Array' do
|
|
50
|
+
let(:dictionary_words) { :not_an_array }
|
|
51
|
+
|
|
52
|
+
it 'raises an error' do
|
|
53
|
+
expect { subject }.to raise_error ArgumentError
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe 'word_filter:' do
|
|
59
|
+
context 'when argument word_filters is nil' do
|
|
60
|
+
it 'no word filters will be used' do
|
|
61
|
+
expect(subject.word_filters).to be_blank
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context 'when argument word_filters is an empty Array ([])' do
|
|
66
|
+
let(:word_filters) { [] }
|
|
67
|
+
|
|
68
|
+
it 'no word filters will be used' do
|
|
69
|
+
expect(subject.word_filters.count).to eq 0
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'when argument word_filters is NOT nil' do
|
|
74
|
+
let(:word_filters) { [WordFilter01.new, WordFilter02.new] }
|
|
75
|
+
|
|
76
|
+
it 'the dictionary will use the word filters passed' do
|
|
77
|
+
expect(subject.word_filters.count).to eq 2
|
|
78
|
+
expect(subject.word_filters).to include(a_kind_of(WordFilter01))
|
|
79
|
+
expect(subject.word_filters).to include(a_kind_of(WordFilter02))
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
#.to_hash
|
|
86
|
+
describe '.to_hash' do
|
|
87
|
+
let(:expected_hash) do
|
|
88
|
+
{
|
|
89
|
+
'this' => true,
|
|
90
|
+
'is' => true,
|
|
91
|
+
'a' => true,
|
|
92
|
+
'test' => true
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'returns a Hash of dictionary words' do
|
|
97
|
+
expect(described_class.to_hash(dictionary_words: %w(this is a test))).to eq expected_hash
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
#detached?
|
|
102
|
+
describe '#detached?' do
|
|
103
|
+
before do
|
|
104
|
+
subject
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: dictionary_key.key, load: true) }
|
|
108
|
+
|
|
109
|
+
context 'when the dictionary object is in the dictionary cache' do
|
|
110
|
+
it 'returns false' do
|
|
111
|
+
dictionary_cache_service
|
|
112
|
+
expect(dictionary_cache_service.dictionary_object?).to eq true
|
|
113
|
+
expect(subject.detached?).to eq false
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
context 'when the dictionary object is NOT in the dictionary cache' do
|
|
118
|
+
before do
|
|
119
|
+
dictionary_cache_service
|
|
120
|
+
dictionary_killer_service = create(:dictionary_killer_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata)
|
|
121
|
+
dictionary_killer_service.execute
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'returns true' do
|
|
125
|
+
expect(dictionary_cache_service.dictionary_object?).to eq false
|
|
126
|
+
expect(subject.detached?).to eq true
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
#key
|
|
132
|
+
describe '#key' do
|
|
133
|
+
it 'returns the expected key' do
|
|
134
|
+
expect(subject.key).to eq dictionary_key.key
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#count
|
|
139
|
+
describe '#count' do
|
|
140
|
+
before do
|
|
141
|
+
subject.word_results('badword')
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it 'returns the count of all valid words' do
|
|
145
|
+
expect(subject.count).to eq dictionary_words.count
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
#count_all_words
|
|
150
|
+
describe '#count_all_words' do
|
|
151
|
+
before do
|
|
152
|
+
subject.word_results('badword')
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it 'returns the count of all valid and invalid words' do
|
|
156
|
+
expect(subject.count_all_words).to eq dictionary_words.count + 1
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
#count_invalid_words
|
|
161
|
+
describe '#count_invalid_words' do
|
|
162
|
+
before do
|
|
163
|
+
subject.word_results('badword')
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'returns the count of all invalid words' do
|
|
167
|
+
expect(subject.count_invalid_words).to eq 1
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
#word_results
|
|
172
|
+
describe '#word_results' do
|
|
173
|
+
context 'when argument word is INVALID' do
|
|
174
|
+
context 'when not a String' do
|
|
175
|
+
let(:word) { :not_a_string }
|
|
176
|
+
|
|
177
|
+
it 'raises an error' do
|
|
178
|
+
expect { subject.word_results(word) }.to raise_error "Argument word is not a String: #{word.class}"
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context 'when searching for words in the dictionary' do
|
|
184
|
+
context 'when the word is found' do
|
|
185
|
+
it 'returns true' do
|
|
186
|
+
expect(subject.word_results('dog').success?).to eq true
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context 'when the word is not found' do
|
|
191
|
+
it 'returns false' do
|
|
192
|
+
expect(subject.word_results('badword').success?).to eq false
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
#block_results
|
|
199
|
+
describe '#block_results' do
|
|
200
|
+
context 'when nil is passed' do
|
|
201
|
+
it 'raises an error' do
|
|
202
|
+
expect { subject.block_results nil }.to raise_error(/Argument word_block is not a String/)
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
context 'when an empty String is passed' do
|
|
207
|
+
it 'raises an error' do
|
|
208
|
+
expect { subject.block_results '' }.to raise_error(/Argument word_block is empty/)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
context 'when a valid block of words is passed' do
|
|
213
|
+
subject do
|
|
214
|
+
create(:dictionary,
|
|
215
|
+
dictionary_key: dictionary_key,
|
|
216
|
+
dictionary_cache: dictionary_cache,
|
|
217
|
+
dictionary_words: dictionary_words,
|
|
218
|
+
word_filters: word_filters).block_results word_block
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
let(:word_filters) { [LittleWeasel::Filters::EnUs::NumericFilter.new] }
|
|
222
|
+
let(:word_block) do
|
|
223
|
+
"I'm older than you bubble-butt; I was born in 1964, before your time!"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'returns a WordResults object with the correct data about the words passed' do
|
|
227
|
+
DictionaryResultsHelpers.print_block_results word_block, subject
|
|
228
|
+
|
|
229
|
+
expect(subject.word_results.count).to eq 13
|
|
230
|
+
expect(block_results_include?(subject, "I'm")).to eq [true, true]
|
|
231
|
+
expect(block_results_include?(subject, 'older')).to eq [true, true]
|
|
232
|
+
expect(block_results_include?(subject, 'than')).to eq [true, true]
|
|
233
|
+
expect(block_results_include?(subject, 'you')).to eq [true, true]
|
|
234
|
+
expect(block_results_include?(subject, 'bubble-butt')).to eq [true, false]
|
|
235
|
+
expect(block_results_include?(subject, 'I')).to eq [true, true]
|
|
236
|
+
expect(block_results_include?(subject, 'was')).to eq [true, true]
|
|
237
|
+
expect(block_results_include?(subject, 'born')).to eq [true, true]
|
|
238
|
+
expect(block_results_include?(subject, 'in')).to eq [true, true]
|
|
239
|
+
expect(block_results_include?(subject, '1964')).to eq [true, false]
|
|
240
|
+
expect(block_results_include?(subject, 'before')).to eq [true, true]
|
|
241
|
+
expect(block_results_include?(subject, 'your')).to eq [true, true]
|
|
242
|
+
expect(block_results_include?(subject, 'time')).to eq [true, true]
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Configuration
|
|
248
|
+
context 'configuration options that alter behavior' do
|
|
249
|
+
context 'when max_invalid_words_bytesize? is true' do
|
|
250
|
+
context 'when a word is not found' do
|
|
251
|
+
context 'when the max_invalid_words_bytesize threashold has not been exceeded' do
|
|
252
|
+
it 'adds the word to the cache' do
|
|
253
|
+
expect { subject.word_results('badword') }.to change { subject.count_all_words }.by(1)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context 'when the max_invalid_words_bytesize threashold HAS been exceeded' do
|
|
258
|
+
before do
|
|
259
|
+
LittleWeasel.configure { |config| config.max_invalid_words_bytesize = 30 }
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'does NOT add the word to the cache' do
|
|
263
|
+
expect do
|
|
264
|
+
subject.word_results('IWillBeCached01')
|
|
265
|
+
subject.word_results('IWillBeCached02')
|
|
266
|
+
subject.word_results('IWontBeCached01')
|
|
267
|
+
subject.word_results('IWontBeCached02')
|
|
268
|
+
end.to change { subject.count_all_words }.by(2)
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context 'when max_invalid_words_bytesize? is false' do
|
|
275
|
+
before do
|
|
276
|
+
LittleWeasel.configure { |config| config.max_invalid_words_bytesize = 0 }
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it 'does NOT add the word to the cache' do
|
|
280
|
+
expect do
|
|
281
|
+
subject.word_results('IWillBeCached01')
|
|
282
|
+
subject.word_results('IWillBeCached02')
|
|
283
|
+
subject.word_results('IWontBeCached01')
|
|
284
|
+
subject.word_results('IWontBeCached02')
|
|
285
|
+
end.to change { subject.count_all_words }.by(0)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Filters::EnUs::CurrencyFilter do
|
|
6
|
+
subject { described_class.new }
|
|
7
|
+
|
|
8
|
+
#filter_match?
|
|
9
|
+
describe 'filter_match?' do
|
|
10
|
+
context 'when word is currency' do
|
|
11
|
+
it 'returns true' do
|
|
12
|
+
expect(subject.filter_match?('-$1.00')).to eq true
|
|
13
|
+
expect(subject.filter_match?('-$1')).to eq true
|
|
14
|
+
expect(subject.filter_match?('$0')).to eq true
|
|
15
|
+
expect(subject.filter_match?('$1')).to eq true
|
|
16
|
+
expect(subject.filter_match?('$100')).to eq true
|
|
17
|
+
expect(subject.filter_match?('$100.10')).to eq true
|
|
18
|
+
expect(subject.filter_match?('$123456')).to eq true
|
|
19
|
+
expect(subject.filter_match?('+$110.09')).to eq true
|
|
20
|
+
expect(subject.filter_match?('-$1,000.09')).to eq true
|
|
21
|
+
expect(subject.filter_match?('$1000000.00')).to eq true
|
|
22
|
+
expect(subject.filter_match?('$1100000.10')).to eq true
|
|
23
|
+
expect(subject.filter_match?('$120000.01')).to eq true
|
|
24
|
+
expect(subject.filter_match?('$1,000,000.01')).to eq true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'when word has decimals, but not 2 decimal places' do
|
|
29
|
+
it 'returns false' do
|
|
30
|
+
expect(subject.filter_match?('-$1.1')).to eq false
|
|
31
|
+
expect(subject.filter_match?('$0.1')).to eq false
|
|
32
|
+
expect(subject.filter_match?('$100.9')).to eq false
|
|
33
|
+
expect(subject.filter_match?('+$100.2')).to eq false
|
|
34
|
+
expect(subject.filter_match?('$1000000.0')).to eq false
|
|
35
|
+
expect(subject.filter_match?('$1000000.1')).to eq false
|
|
36
|
+
expect(subject.filter_match?('$1000000.5')).to eq false
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'when word is NOT currency' do
|
|
41
|
+
it 'returns false' do
|
|
42
|
+
expect(subject.filter_match? 'a').to eq false
|
|
43
|
+
expect(subject.filter_match? :a).to eq false
|
|
44
|
+
expect(subject.filter_match? Object.new).to eq false
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
let(:word) { 1 }
|
|
49
|
+
|
|
50
|
+
context 'when #filter_match? returns true' do
|
|
51
|
+
before { allow(subject.class).to receive(:filter_match?).and_return(true) }
|
|
52
|
+
|
|
53
|
+
context 'when #filter_on? is true' do
|
|
54
|
+
it_behaves_like 'the filter matches and #filter_on? is true'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context 'when #filter_on? is false' do
|
|
58
|
+
before do
|
|
59
|
+
subject.filter_on = false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it_behaves_like 'the filter matches and #filter_on? is false'
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'when #filter_match? returns false' do
|
|
67
|
+
before { allow(subject.class).to receive(:filter_match?).and_return(false) }
|
|
68
|
+
|
|
69
|
+
context 'when #filter_on? is true' do
|
|
70
|
+
it_behaves_like 'the filter DOES NOT match and #filter_on? is true'
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context 'when #filter_on? is false' do
|
|
74
|
+
let(:filter_on) { false }
|
|
75
|
+
|
|
76
|
+
it_behaves_like 'the filter DOES NOT match and #filter_on? is false'
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Filters::EnUs::NumericFilter do
|
|
6
|
+
subject { described_class.new }
|
|
7
|
+
|
|
8
|
+
#filter_match?
|
|
9
|
+
describe 'filter_match?' do
|
|
10
|
+
context 'when word is a number' do
|
|
11
|
+
it 'returns true' do
|
|
12
|
+
expect(subject.filter_match?('-1.00')).to eq true
|
|
13
|
+
expect(subject.filter_match?('-1')).to eq true
|
|
14
|
+
expect(subject.filter_match?('0')).to eq true
|
|
15
|
+
expect(subject.filter_match?('1')).to eq true
|
|
16
|
+
expect(subject.filter_match?('100')).to eq true
|
|
17
|
+
expect(subject.filter_match?('100.10')).to eq true
|
|
18
|
+
expect(subject.filter_match?(1234_56)).to eq true
|
|
19
|
+
expect(subject.filter_match?('+100.0')).to eq true
|
|
20
|
+
expect(subject.filter_match?(1_000_000.00)).to eq true
|
|
21
|
+
expect(subject.filter_match?(1_000_000.10)).to eq true
|
|
22
|
+
expect(subject.filter_match?(1_000_000.01)).to eq true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'when word is NOT a number' do
|
|
27
|
+
it 'returns false' do
|
|
28
|
+
expect(subject.filter_match? 'a').to eq false
|
|
29
|
+
expect(subject.filter_match? :a).to eq false
|
|
30
|
+
expect(subject.filter_match? Object.new).to eq false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
let(:word) { 1 }
|
|
35
|
+
|
|
36
|
+
context 'when #filter_match? returns true' do
|
|
37
|
+
before { allow(subject.class).to receive(:filter_match?).and_return(true) }
|
|
38
|
+
|
|
39
|
+
context 'when #filter_on? is true' do
|
|
40
|
+
it_behaves_like 'the filter matches and #filter_on? is true'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'when #filter_on? is false' do
|
|
44
|
+
before do
|
|
45
|
+
subject.filter_on = false
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it_behaves_like 'the filter matches and #filter_on? is false'
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context 'when #filter_match? returns false' do
|
|
53
|
+
before { allow(subject.class).to receive(:filter_match?).and_return(false) }
|
|
54
|
+
|
|
55
|
+
context 'when #filter_on? is true' do
|
|
56
|
+
it_behaves_like 'the filter DOES NOT match and #filter_on? is true'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'when #filter_on? is false' do
|
|
60
|
+
let(:filter_on) { false }
|
|
61
|
+
|
|
62
|
+
it_behaves_like 'the filter DOES NOT match and #filter_on? is false'
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Filters::EnUs::SingleCharacterWordFilter do
|
|
6
|
+
subject { described_class.new }
|
|
7
|
+
|
|
8
|
+
#filter_match?
|
|
9
|
+
describe '#filter_match?' do
|
|
10
|
+
context 'when word single character word' do
|
|
11
|
+
it 'returns true' do
|
|
12
|
+
%w(a A I).each do |number|
|
|
13
|
+
expect(subject.filter_match? number).to eq true
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context 'when word is NOT a single character word' do
|
|
19
|
+
it 'returns false' do
|
|
20
|
+
expect(subject.filter_match? 'X').to eq false
|
|
21
|
+
expect(subject.filter_match? :a).to eq false
|
|
22
|
+
expect(subject.filter_match? Object.new).to eq false
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
let(:word) { 'x' }
|
|
27
|
+
|
|
28
|
+
context 'when #filter_match? returns true' do
|
|
29
|
+
before { allow(subject.class).to receive(:filter_match?).and_return(true) }
|
|
30
|
+
|
|
31
|
+
context 'when #filter_on? is true' do
|
|
32
|
+
it_behaves_like 'the filter matches and #filter_on? is true'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'when #filter_on? is false' do
|
|
36
|
+
before do
|
|
37
|
+
subject.filter_on = false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it_behaves_like 'the filter matches and #filter_on? is false'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'when #filter_match? returns false' do
|
|
45
|
+
before { allow(subject.class).to receive(:filter_match?).and_return(false) }
|
|
46
|
+
|
|
47
|
+
context 'when #filter_on? is true' do
|
|
48
|
+
it_behaves_like 'the filter DOES NOT match and #filter_on? is true'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when #filter_on? is false' do
|
|
52
|
+
let(:filter_on) { false }
|
|
53
|
+
|
|
54
|
+
it_behaves_like 'the filter DOES NOT match and #filter_on? is false'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|