LittleWeasel 3.0.4 → 4.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/Gemfile +3 -1
- data/LittleWeasel.gemspec +31 -18
- data/README.md +408 -42
- data/Rakefile +296 -3
- data/lib/LittleWeasel.rb +5 -184
- 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 +85 -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 +136 -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 +20 -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 +19 -0
- data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
- data/lib/LittleWeasel/modules/dictionary_loader_servicable.rb +27 -0
- data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
- data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +17 -0
- data/lib/LittleWeasel/modules/dictionary_sourceable.rb +26 -0
- data/lib/LittleWeasel/modules/dictionary_validatable.rb +30 -0
- data/lib/LittleWeasel/modules/language.rb +23 -0
- data/lib/LittleWeasel/modules/language_validatable.rb +16 -0
- data/lib/LittleWeasel/modules/locale.rb +40 -0
- data/lib/LittleWeasel/modules/order_validatable.rb +18 -0
- data/lib/LittleWeasel/modules/orderable.rb +17 -0
- data/lib/LittleWeasel/modules/region.rb +23 -0
- data/lib/LittleWeasel/modules/region_validatable.rb +16 -0
- data/lib/LittleWeasel/modules/tag_validatable.rb +16 -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 +28 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +55 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +55 -0
- data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +27 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
- data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +122 -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 +262 -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_loader_service.rb +59 -0
- data/lib/LittleWeasel/services/dictionary_metadata_service.rb +114 -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/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_loader_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 +116 -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 +44 -0
- data/spec/lib/LittleWeasel/modules/language_spec.rb +52 -0
- data/spec/lib/LittleWeasel/modules/locale_spec.rb +140 -0
- data/spec/lib/LittleWeasel/modules/region_spec.rb +52 -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 +216 -0
- data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +175 -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_loader_service_spec.rb +50 -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 +32 -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 +108 -0
- data/spec/support/shared_examples.rb +105 -0
- metadata +408 -65
- data/spec/checker/checker_spec.rb +0 -286
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel do
|
|
6
|
+
subject do
|
|
7
|
+
described_class.configure { |config| }
|
|
8
|
+
described_class.configuration
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context 'default configurable settings' do
|
|
12
|
+
describe '#max_dictionary_file_megabytes' do
|
|
13
|
+
it 'set to 5 by default' do
|
|
14
|
+
expect(subject.max_dictionary_file_megabytes).to eq 5
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe '#max_invalid_words_bytesize' do
|
|
19
|
+
it 'set to 25_000 by default' do
|
|
20
|
+
expect(subject.max_invalid_words_bytesize).to eq 25_000
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe '#metadata_observers' do
|
|
25
|
+
it 'set to an Array with InvalidWordsMetadata by default' do
|
|
26
|
+
expect(subject.metadata_observers).to eq [
|
|
27
|
+
LittleWeasel::Metadata::InvalidWordsMetadata
|
|
28
|
+
]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#word_block_regex' do
|
|
33
|
+
it 'set to the default regex to split work blocks by default' do
|
|
34
|
+
expect(subject.word_block_regex).to eq /[[[:word:]]'-]+/
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#.configuration
|
|
40
|
+
describe '.configuration' do
|
|
41
|
+
context 'when passing a block' do
|
|
42
|
+
subject do
|
|
43
|
+
described_class.configure do |config|
|
|
44
|
+
config.max_dictionary_file_megabytes = max_dictionary_file_megabytes
|
|
45
|
+
config.metadata_observers = metadata_observers
|
|
46
|
+
config.word_block_regex = word_block_regex
|
|
47
|
+
end
|
|
48
|
+
described_class.configuration
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
let(:max_dictionary_file_megabytes) { 1_222_333 }
|
|
52
|
+
let(:metadata_observers) { %i(observer0 observer1) }
|
|
53
|
+
let(:word_block_regex) { :word_block_regex }
|
|
54
|
+
|
|
55
|
+
describe '#max_dictionary_file_megabytes=' do
|
|
56
|
+
it 'sets the value' do
|
|
57
|
+
expect(subject.max_dictionary_file_megabytes).to eq max_dictionary_file_megabytes
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe '#metadata_observers=' do
|
|
62
|
+
it 'sets the value' do
|
|
63
|
+
expect(subject.metadata_observers).to eq metadata_observers
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe '#word_block_regex=' do
|
|
68
|
+
it 'sets the value' do
|
|
69
|
+
expect(subject.word_block_regex).to eq word_block_regex
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::DictionaryKey, type: :class do
|
|
6
|
+
subject { described_class.new(language: language, region: region, tag: tag) }
|
|
7
|
+
|
|
8
|
+
let(:language) {}
|
|
9
|
+
let(:region) {}
|
|
10
|
+
let(:tag) {}
|
|
11
|
+
|
|
12
|
+
#.new
|
|
13
|
+
describe '.new' do
|
|
14
|
+
context 'when passing valid arguments' do
|
|
15
|
+
let(:language) { :EN }
|
|
16
|
+
let(:region) { :us }
|
|
17
|
+
let(:tag) { :TAGGED}
|
|
18
|
+
|
|
19
|
+
it 'instantiates the object' do
|
|
20
|
+
expect { subject }.to_not raise_error
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'normalizes language and converts it to lowercase' do
|
|
24
|
+
expect(subject.language).to eq :en
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'normalizes region and converts it to uppercase' do
|
|
28
|
+
expect(subject.region).to eq :US
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'leaves tag case unchanged' do
|
|
32
|
+
expect(subject.tag).to eq :TAGGED
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
context 'when passing invalid arguments' do
|
|
37
|
+
context 'when passing an invalid language' do
|
|
38
|
+
it 'raises an error' do
|
|
39
|
+
expect { subject }.to raise_error "Argument language '#{language}' is not a Symbol."
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'when passing an invalid region' do
|
|
44
|
+
let(:language) { :en }
|
|
45
|
+
let(:region) { 1 }
|
|
46
|
+
|
|
47
|
+
it 'raises an error' do
|
|
48
|
+
expect { subject }.to raise_error "Argument region '#{region}' is not a Symbol."
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#.key
|
|
55
|
+
describe '.key' do
|
|
56
|
+
let(:language) { :xx }
|
|
57
|
+
let(:region) { :yy }
|
|
58
|
+
let(:tag) { :zz }
|
|
59
|
+
|
|
60
|
+
it 'returns the locale' do
|
|
61
|
+
expect(described_class.key language: language, region: region, tag: tag).to eq 'xx-YY-zz'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#key
|
|
66
|
+
describe '#key' do
|
|
67
|
+
context 'with no tag' do
|
|
68
|
+
context 'with language' do
|
|
69
|
+
let(:language) { :EN }
|
|
70
|
+
|
|
71
|
+
it 'returns the key in the form of a locale String that includes language only (e.g. "en")' do
|
|
72
|
+
expect(subject.key).to eq 'en'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context 'with language and region' do
|
|
77
|
+
let(:language) { :EN }
|
|
78
|
+
let(:region) { :us }
|
|
79
|
+
|
|
80
|
+
it 'returns the key in the form of a locale String that includes language and region (e.g. "en-US")' do
|
|
81
|
+
expect(subject.key).to eq 'en-US'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context 'with a tag' do
|
|
87
|
+
let(:tag) { :tagged }
|
|
88
|
+
|
|
89
|
+
context 'with language and a tag' do
|
|
90
|
+
let(:language) { :EN }
|
|
91
|
+
|
|
92
|
+
it 'returns the key in the form of a locale String that includes the language and appended tag (e.g. "en-tag")' do
|
|
93
|
+
expect(subject.key).to eq 'en-tagged'
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'with language and region' do
|
|
98
|
+
let(:language) { :EN }
|
|
99
|
+
let(:region) { :us }
|
|
100
|
+
|
|
101
|
+
it 'returns the key in the form of a locale String that includes language, region and the appended tag (e.g. "en-US-tag")' do
|
|
102
|
+
expect(subject.key).to eq 'en-US-tagged'
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#to_s
|
|
109
|
+
describe '#to_s' do
|
|
110
|
+
let(:language) { :en }
|
|
111
|
+
let(:region) { :us }
|
|
112
|
+
let(:tag) { :tagged }
|
|
113
|
+
|
|
114
|
+
it '#to_s is an alias for #key' do
|
|
115
|
+
expect(subject.to_s).to eq 'en-US-tagged'
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::DictionaryManager do
|
|
6
|
+
subject { create(:dictionary_manager) }
|
|
7
|
+
|
|
8
|
+
let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache)}
|
|
9
|
+
let(:dictionary_metadata_service) { create(:dictionary_metadata_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata)}
|
|
10
|
+
let(:dictionary_key) { create(:dictionary_key, language: language, region: region, tag: tag) }
|
|
11
|
+
let(:dictionary_cache) { subject.dictionary_cache }
|
|
12
|
+
let(:dictionary_metadata) { subject.dictionary_metadata }
|
|
13
|
+
|
|
14
|
+
let(:language) { :en }
|
|
15
|
+
let(:region) { :us }
|
|
16
|
+
let(:tag) {}
|
|
17
|
+
let(:file) { dictionary_path_for(file_name: dictionary_key.key) }
|
|
18
|
+
|
|
19
|
+
let(:metadata_key) do
|
|
20
|
+
dictionary_cache_service.dictionary_object.dictionary_metadata_object.observers.keys.first
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
before(:each) do
|
|
24
|
+
subject.init
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#.new
|
|
28
|
+
describe '.new' do
|
|
29
|
+
it 'does not raise an error' do
|
|
30
|
+
expect { subject }.not_to raise_error
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#create_dictionary_from_file
|
|
35
|
+
describe '#create_dictionary_from_file' do
|
|
36
|
+
context 'when the dictionary DOES NOT exist' do
|
|
37
|
+
it 'creates a dictionary and returns a dictionary object' do
|
|
38
|
+
expect(subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)).to be_kind_of LittleWeasel::Dictionary
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
context 'when the dictionary already exists' do
|
|
43
|
+
before do
|
|
44
|
+
subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'raises an error' do
|
|
48
|
+
expect { subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file) }
|
|
49
|
+
.to raise_error("The dictionary source associated with key '#{dictionary_key.key}' already exists.")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#create_dictionary_from_memory
|
|
55
|
+
describe '#create_dictionary_from_memory' do
|
|
56
|
+
let(:dictionary_words) { dictionary_words_for(dictionary_file_path: file) }
|
|
57
|
+
|
|
58
|
+
context 'when the dictionary reference does not exist and the dictionary is not cached' do
|
|
59
|
+
it 'adds a dictionary reference caches the dictionary and returns a dictionary object' do
|
|
60
|
+
expect(subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words)).to be_kind_of LittleWeasel::Dictionary
|
|
61
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq true
|
|
62
|
+
expect(dictionary_cache_service.dictionary_object?).to eq true
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context 'when the dictionary reference exists' do
|
|
67
|
+
before do
|
|
68
|
+
subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'raises an error' do
|
|
72
|
+
expect { subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words) }
|
|
73
|
+
.to raise_error "The dictionary source associated with key '#{dictionary_key.key}' already exists."
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
#kill
|
|
79
|
+
describe '#kill_dictionary' do
|
|
80
|
+
context 'dictionaries created from files' do
|
|
81
|
+
before do
|
|
82
|
+
subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it 'removes the dictionary, file source reference and metadata from the dictionary cache' do
|
|
86
|
+
metadata_key # Capture this before we unload the dictionary
|
|
87
|
+
subject.kill_dictionary(dictionary_key: dictionary_key)
|
|
88
|
+
expect(dictionary_cache_service.dictionary_exists?).to eq false
|
|
89
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq false
|
|
90
|
+
expect(dictionary_metadata_service.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'returns the dictionary manager instance' do
|
|
94
|
+
expect(subject.kill_dictionary(dictionary_key: dictionary_key)).to eq subject
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context 'dictionaries created from memory' do
|
|
99
|
+
before do
|
|
100
|
+
subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: %w(Abel Cain Deborah Elijah))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'removes the dictionary, memory source reference and metadata from the dictionary cache' do
|
|
104
|
+
metadata_key # Capture this before we unload the dictionary
|
|
105
|
+
subject.kill_dictionary(dictionary_key: dictionary_key)
|
|
106
|
+
expect(dictionary_cache_service.dictionary_exists?).to eq false
|
|
107
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq false
|
|
108
|
+
expect(dictionary_metadata_service.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'returns the dictionary manager instance' do
|
|
112
|
+
expect(subject.kill_dictionary(dictionary_key: dictionary_key)).to eq subject
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
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
|