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,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
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Modules::ClassNameToSymbol, type: :module do
|
|
6
|
+
ClassNameToSymbol = described_class
|
|
7
|
+
|
|
8
|
+
subject do
|
|
9
|
+
module TestModule
|
|
10
|
+
class TestMeUp
|
|
11
|
+
include ClassNameToSymbol
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '#to_sym' do
|
|
17
|
+
it 'returns the class name as a snake-case Symbol with namespaces removed' do
|
|
18
|
+
expect(subject.new.to_sym).to eq :test_me_up
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Modules::DictionaryFileLoader, type: :module do
|
|
6
|
+
subject do
|
|
7
|
+
dictionary_cache_service.init dictionary_cache: dictionary_cache
|
|
8
|
+
dictionary_file_loader
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:dictionary_file_loader) do
|
|
12
|
+
Class.new do
|
|
13
|
+
include LittleWeasel::Modules::DictionaryFileLoader
|
|
14
|
+
|
|
15
|
+
attr_reader :dictionary_key, :dictionary_cache, :config
|
|
16
|
+
|
|
17
|
+
def initialize(dictionary_key, dictionary_cache)
|
|
18
|
+
self.dictionary_key = dictionary_key
|
|
19
|
+
self.dictionary_cache = dictionary_cache
|
|
20
|
+
self.config = LittleWeasel.configuration
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
attr_writer :dictionary_key, :dictionary_cache, :config
|
|
26
|
+
end.new(dictionary_key, dictionary_cache)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let(:language) { :en }
|
|
30
|
+
let(:region) { :us }
|
|
31
|
+
let(:tag) {}
|
|
32
|
+
|
|
33
|
+
let(:dictionary_cache_service) { LittleWeasel::Services::DictionaryCacheService }
|
|
34
|
+
let(:dictionary_key) { LittleWeasel::DictionaryKey.new(language: language, region: region, tag: tag) }
|
|
35
|
+
let(:key) { dictionary_key.key }
|
|
36
|
+
let(:file) { dictionary_path_for locale: dictionary_key.locale }
|
|
37
|
+
let(:dictionary_file_key) { file }
|
|
38
|
+
let(:dictionary_cache) { {} }
|
|
39
|
+
|
|
40
|
+
#load
|
|
41
|
+
describe '#load' do
|
|
42
|
+
context 'with an invalid dictionary file' do
|
|
43
|
+
context 'when it cannot be found' do
|
|
44
|
+
let(:dictionary_path) { region_dictionary_path language: :bad, region: :worse }
|
|
45
|
+
|
|
46
|
+
it 'raises an error' do
|
|
47
|
+
expect { subject.load dictionary_path }.to raise_error LittleWeasel::Errors::DictionaryFileNotFoundError
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
context 'when it is empty' do
|
|
52
|
+
let(:dictionary_path) { dictionary_path_for file_name: 'empty-dictionary' }
|
|
53
|
+
|
|
54
|
+
it 'raises an error' do
|
|
55
|
+
expect { subject.load dictionary_path }.to raise_error LittleWeasel::Errors::DictionaryFileEmptyError
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'when it is too large' do
|
|
60
|
+
before do
|
|
61
|
+
allow(LittleWeasel.configuration).to receive(:max_dictionary_file_bytes).and_return 1
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
let(:dictionary_path) { language_dictionary_path language: :en }
|
|
65
|
+
|
|
66
|
+
it 'raises an error' do
|
|
67
|
+
expect { subject.load dictionary_path }.to raise_error LittleWeasel::Errors::DictionaryFileTooLargeError
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context 'with a valid dictionary file' do
|
|
73
|
+
subject { dictionary_file_loader.load dictionary_path }
|
|
74
|
+
|
|
75
|
+
let(:dictionary_path) { region_dictionary_path language: language, region: region }
|
|
76
|
+
|
|
77
|
+
context 'when the dictionary file is already loaded/cached' do
|
|
78
|
+
before { subject }
|
|
79
|
+
|
|
80
|
+
it 'does not raise an error' do
|
|
81
|
+
expect { subject }.to_not raise_error
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context 'when the dictionary is NOT already loaded/cached' do
|
|
86
|
+
let(:expected_dictionary_key_key) { LittleWeasel::DictionaryKey.new(language: language, region: region, tag: tag).key }
|
|
87
|
+
let(:expected_results) do
|
|
88
|
+
['apple',
|
|
89
|
+
'better',
|
|
90
|
+
'cat',
|
|
91
|
+
'dog',
|
|
92
|
+
'everyone',
|
|
93
|
+
'fat',
|
|
94
|
+
'game',
|
|
95
|
+
'help',
|
|
96
|
+
'italic',
|
|
97
|
+
'jasmine',
|
|
98
|
+
'kelp',
|
|
99
|
+
'love',
|
|
100
|
+
'man',
|
|
101
|
+
'nope',
|
|
102
|
+
'octopus',
|
|
103
|
+
'popeye',
|
|
104
|
+
'queue',
|
|
105
|
+
'ruby',
|
|
106
|
+
'stop',
|
|
107
|
+
'top',
|
|
108
|
+
'ultimate',
|
|
109
|
+
'very',
|
|
110
|
+
'was',
|
|
111
|
+
'xylophone',
|
|
112
|
+
'yes',
|
|
113
|
+
'zebra']
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'returns an Array of dictionary words loaded from the file' do
|
|
117
|
+
# This test won't pass if we're not testing against an assumed
|
|
118
|
+
# dictionary file.
|
|
119
|
+
expect(dictionary_key.key).to eq expected_dictionary_key_key
|
|
120
|
+
expect(subject).to eq expected_results
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|