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,119 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Services::DictionaryCreatorService do
|
|
6
|
+
include_context 'dictionary keys'
|
|
7
|
+
include_context 'mock word filters'
|
|
8
|
+
include_context 'mock word preprocessors'
|
|
9
|
+
|
|
10
|
+
subject { create(:dictionary_creator_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata, word_filters: word_filters, word_preprocessors: word_preprocessors) }
|
|
11
|
+
|
|
12
|
+
let(:language) { :en }
|
|
13
|
+
let(:region) { :us }
|
|
14
|
+
let(:tag) {}
|
|
15
|
+
let(:dictionary_key) { create(:dictionary_key, language: language, region: region, tag: tag) }
|
|
16
|
+
let(:key) { dictionary_key.key }
|
|
17
|
+
let(:file) { dictionary_path_for(file_name: key) }
|
|
18
|
+
let(:dictionary_cache) { {} }
|
|
19
|
+
let(:dictionary_metadata) { {} }
|
|
20
|
+
let(:word_filters) {}
|
|
21
|
+
let(:word_preprocessors) {}
|
|
22
|
+
|
|
23
|
+
shared_examples 'it should' do
|
|
24
|
+
context 'with word_filters' do
|
|
25
|
+
context 'when argument word_filters contains word filters' do
|
|
26
|
+
let(:word_filters) do
|
|
27
|
+
[
|
|
28
|
+
DollarSignFilter.new,
|
|
29
|
+
LittleWeasel::Filters::EnUs::NumericFilter.new,
|
|
30
|
+
LittleWeasel::Filters::EnUs::SingleCharacterWordFilter.new
|
|
31
|
+
]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'creates a dictionary with the word filters passed' do
|
|
35
|
+
expect(dictionary).to be_kind_of LittleWeasel::Dictionary
|
|
36
|
+
expect(dictionary.word_results('$').success?).to eq true
|
|
37
|
+
expect(dictionary.word_results('1000').success?).to eq true
|
|
38
|
+
expect(dictionary.word_results('A').success?).to eq true
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context 'with NO word_filters' do
|
|
44
|
+
context 'when argument word_filters is an empty Array' do
|
|
45
|
+
let(:word_filters) { [] }
|
|
46
|
+
|
|
47
|
+
it 'creates a dictionary that uses no word filters' do
|
|
48
|
+
expect(dictionary).to be_kind_of LittleWeasel::Dictionary
|
|
49
|
+
expect(dictionary.word_filters).to be_blank
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'when argument word_filters is nil' do
|
|
54
|
+
let(:word_filters) {}
|
|
55
|
+
|
|
56
|
+
it 'creates a dictionary that uses no word filters' do
|
|
57
|
+
expect(dictionary).to be_kind_of LittleWeasel::Dictionary
|
|
58
|
+
expect(dictionary.word_filters).to be_blank
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'with word_preprocessors' do
|
|
64
|
+
let(:word_preprocessors) { [UpcaseWordPreprocessor.new(order: 0)] }
|
|
65
|
+
let(:word) { 'a' }
|
|
66
|
+
|
|
67
|
+
context 'when argument word_preprocessors contains word preprocessors' do
|
|
68
|
+
it 'creates a dictionary with the word preprocessors passed' do
|
|
69
|
+
expect(dictionary).to be_kind_of LittleWeasel::Dictionary
|
|
70
|
+
preprocessed_words = dictionary.word_results(word).preprocessed_words
|
|
71
|
+
expect(preprocessed_words.original_word).to eq word
|
|
72
|
+
expect(preprocessed_words.preprocessed_words.count).to eq 1
|
|
73
|
+
expect(preprocessed_words.preprocessed_words[0].original_word).to eq word
|
|
74
|
+
expect(preprocessed_words.preprocessed_words[0].preprocessed_word).to eq word.upcase
|
|
75
|
+
expect(preprocessed_words.preprocessed_words[0].preprocessor).to eq word_preprocessors[0].to_sym
|
|
76
|
+
expect(preprocessed_words.preprocessed_words[0].preprocessed).to eq true
|
|
77
|
+
expect(preprocessed_words.preprocessed_words[0].preprocessor_order).to eq word_preprocessors[0].order
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'with NO word_preprocessors' do
|
|
83
|
+
context 'when argument word_preprocessors is an empty Array' do
|
|
84
|
+
let(:word_preprocessors) { [] }
|
|
85
|
+
|
|
86
|
+
it 'creates a dictionary that uses no word preprocessors' do
|
|
87
|
+
expect(dictionary).to be_kind_of LittleWeasel::Dictionary
|
|
88
|
+
expect(dictionary.word_preprocessors).to be_blank
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'when argument word_preprocessors is nil' do
|
|
93
|
+
let(:word_preprocessors) {}
|
|
94
|
+
|
|
95
|
+
it 'creates a dictionary that uses no word preprocessors' do
|
|
96
|
+
expect(dictionary).to be_kind_of LittleWeasel::Dictionary
|
|
97
|
+
expect(dictionary.word_preprocessors).to be_blank
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
#from_file_source
|
|
104
|
+
describe '#from_file_source' do
|
|
105
|
+
let(:dictionary) { subject.from_file_source file: file }
|
|
106
|
+
|
|
107
|
+
it_behaves_like 'it should'
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#from_memory_source
|
|
111
|
+
describe '#from_memory_source' do
|
|
112
|
+
let(:dictionary) { subject.from_memory_source dictionary_words: dictionary_words }
|
|
113
|
+
let(:dictionary_words) do
|
|
114
|
+
dictionary_words_for dictionary_file_path: file
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it_behaves_like 'it should'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Services::DictionaryFileLoaderService do
|
|
6
|
+
include_context 'dictionary cache'
|
|
7
|
+
|
|
8
|
+
subject! { create(:dictionary_file_loader_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache) }
|
|
9
|
+
|
|
10
|
+
before(:each) do
|
|
11
|
+
LittleWeasel::Services::DictionaryCacheService.init dictionary_cache: dictionary_cache
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let(:dictionary_key) { create(:dictionary_key, language: :en, region: :us) }
|
|
15
|
+
let(:key) { dictionary_key.key }
|
|
16
|
+
let(:dictionary_cache) { {} }
|
|
17
|
+
|
|
18
|
+
#execute
|
|
19
|
+
describe '#execute' do
|
|
20
|
+
context 'when the dictionary is already loaded/cached' do
|
|
21
|
+
before do
|
|
22
|
+
create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: true, load: true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'raises an error' do
|
|
26
|
+
expect { subject.execute }.to raise_error "The dictionary associated with key '#{key}' already exists."
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
context 'when the dictionary is NOT already loaded/cached' do
|
|
31
|
+
before do
|
|
32
|
+
create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: true)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
let(:expected_key) { create(:dictionary_key, language: :en, region: :us).key }
|
|
36
|
+
let(:expected_results) do
|
|
37
|
+
['apple',
|
|
38
|
+
'better',
|
|
39
|
+
'cat',
|
|
40
|
+
'dog',
|
|
41
|
+
'everyone',
|
|
42
|
+
'fat',
|
|
43
|
+
'game',
|
|
44
|
+
'help',
|
|
45
|
+
'italic',
|
|
46
|
+
'jasmine',
|
|
47
|
+
'kelp',
|
|
48
|
+
'love',
|
|
49
|
+
'man',
|
|
50
|
+
'nope',
|
|
51
|
+
'octopus',
|
|
52
|
+
'popeye',
|
|
53
|
+
'queue',
|
|
54
|
+
'ruby',
|
|
55
|
+
'stop',
|
|
56
|
+
'top',
|
|
57
|
+
'ultimate',
|
|
58
|
+
'very',
|
|
59
|
+
'was',
|
|
60
|
+
'xylophone',
|
|
61
|
+
'yes',
|
|
62
|
+
'zebra']
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'returns an Array of dictionary words loaded from the file' do
|
|
66
|
+
expect(key).to eq expected_key
|
|
67
|
+
expect(subject.execute).to eq expected_results
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Services::DictionaryLoaderService do
|
|
6
|
+
subject { create(:dictionary_loader_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata) }
|
|
7
|
+
|
|
8
|
+
let(:language) { :en }
|
|
9
|
+
let(:region) { :us }
|
|
10
|
+
let(:tag) {}
|
|
11
|
+
let(:dictionary_key) { create(:dictionary_key, language: language, region: region, tag: tag) }
|
|
12
|
+
let(:dictionary_cache) { {} }
|
|
13
|
+
let(:dictionary_metadata) { {} }
|
|
14
|
+
|
|
15
|
+
#execute
|
|
16
|
+
describe '#execute' do
|
|
17
|
+
context 'when loading dictionaries created from a file' do
|
|
18
|
+
let!(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_file_source: true, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache) }
|
|
19
|
+
|
|
20
|
+
context 'when the dictionary is not cached' do
|
|
21
|
+
it 'loads the dictionary file and returns the Dictionary' do
|
|
22
|
+
expect(dictionary_cache_service.dictionary_exists?).to be false
|
|
23
|
+
# Remove this line; there is a bug in SimpleCov that will not
|
|
24
|
+
# recognize #load_from_cache as having test coverage if we
|
|
25
|
+
# stub this out :(
|
|
26
|
+
# expect(subject).to_not receive(:load_from_cache)
|
|
27
|
+
expect(subject.execute).to be_kind_of LittleWeasel::Dictionary
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'when the dictionary is cached' do
|
|
32
|
+
before do
|
|
33
|
+
# This will load the dictionary from disk, and cache it in
|
|
34
|
+
# the dictionary cache; the DictionaryLoaderService loads
|
|
35
|
+
# the dictionary into the dictionary cache if loaded from disk.
|
|
36
|
+
subject.execute
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'loads the dictionary from the dictionary cache and returns the Dictionary' do
|
|
40
|
+
expect(dictionary_cache_service.dictionary_exists?).to be true
|
|
41
|
+
# Remove this line; there is a bug in SimpleCov that will not
|
|
42
|
+
# recognize #load_from_cache as having test coverage if we
|
|
43
|
+
# stub this out :(
|
|
44
|
+
# expect(subject).to receive(:load_from_cache).and_return(dictionary_cache_service.dictionary_object!)
|
|
45
|
+
expect(subject.execute).to be dictionary_cache_service.dictionary_object!
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Services::DictionaryMetadataService do
|
|
6
|
+
include_context 'dictionary cache'
|
|
7
|
+
include_context 'dictionary keys'
|
|
8
|
+
|
|
9
|
+
subject { create(:dictionary_metadata_service, dictionary_key: dictionary_key, dictionary_metadata: dictionary_metadata, dictionary_cache: dictionary_cache) }
|
|
10
|
+
|
|
11
|
+
let(:en_us_dictionary_key) { dictionary_key_for(language: :en, region: :us) }
|
|
12
|
+
let(:en_gb_dictionary_key) { dictionary_key_for(language: :en, region: :gb) }
|
|
13
|
+
let(:es_es_dictionary_key) { dictionary_key_for(language: :es, region: :es) }
|
|
14
|
+
|
|
15
|
+
let(:dictionary_key) { en_us_dictionary_key }
|
|
16
|
+
let(:key) { dictionary_key.key }
|
|
17
|
+
let(:file) { dictionary_path_for(file_name: key) }
|
|
18
|
+
let(:dictionary_cache) { {} }
|
|
19
|
+
let(:metadata_key) { :metadata_key }
|
|
20
|
+
let(:dictionary_metadata) do
|
|
21
|
+
{
|
|
22
|
+
0 => { metadata_key => :metadata_object0 },
|
|
23
|
+
1 => { metadata_key1: :metadata_object1 }
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
shared_examples 'the dictionary_metadata object reference has not changed' do
|
|
28
|
+
it 'the dictionary_metadata object has not changed' do
|
|
29
|
+
expect(actual_dictionary_metadata).to be expected_dictionary_metadata
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
shared_examples 'the dictionary_cache object reference has not changed' do
|
|
34
|
+
it 'the dictionary_cache object has not changed' do
|
|
35
|
+
expect(actual_dictionary_cache).to be expected_dictionary_cache
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe 'class methods' do
|
|
40
|
+
#.init
|
|
41
|
+
describe '.init' do
|
|
42
|
+
context 'with a valid dictionary metadata argument' do
|
|
43
|
+
it 'initializes the dictionary metadata' do
|
|
44
|
+
expect(described_class.init(dictionary_metadata: dictionary_metadata)).to eq({})
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it_behaves_like 'the dictionary_metadata object reference has not changed' do
|
|
48
|
+
let(:expected_dictionary_metadata) { dictionary_metadata }
|
|
49
|
+
let(:actual_dictionary_metadata) { subject.dictionary_metadata }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'with an INVALID dictionary metadata argument' do
|
|
54
|
+
subject { described_class.init(dictionary_metadata: dictionary_metadata) }
|
|
55
|
+
|
|
56
|
+
it_behaves_like 'the dictionary_metadata is invalid'
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#.init?
|
|
61
|
+
describe '.init?' do
|
|
62
|
+
context 'with a valid dictionary metadata argument' do
|
|
63
|
+
context 'when the dictionary metadata is in an initialized state' do
|
|
64
|
+
let(:dictionary_metadata) { {} }
|
|
65
|
+
|
|
66
|
+
it 'returns true' do
|
|
67
|
+
expect(described_class.init?(dictionary_metadata: dictionary_metadata)).to eq true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context 'when the dictionary metadata is NOT in an initialized state' do
|
|
72
|
+
it 'returns false' do
|
|
73
|
+
expect(described_class.init?(dictionary_metadata: dictionary_metadata)).to eq false
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context 'with an INVALID dictionary metadata argument' do
|
|
79
|
+
subject { described_class.init?(dictionary_metadata: dictionary_metadata) }
|
|
80
|
+
|
|
81
|
+
it_behaves_like 'the dictionary_metadata is invalid'
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
#.new
|
|
87
|
+
describe '.new' do
|
|
88
|
+
context 'when the arguments are valid' do
|
|
89
|
+
it 'instantiates without errors' do
|
|
90
|
+
expect { subject }.to_not raise_error
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it_behaves_like 'the dictionary_key is invalid'
|
|
95
|
+
it_behaves_like 'the dictionary_cache is invalid'
|
|
96
|
+
it_behaves_like 'the dictionary_metadata is invalid'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#init
|
|
100
|
+
describe '#init' do
|
|
101
|
+
let(:expected_dictionary_metadata) do
|
|
102
|
+
{
|
|
103
|
+
0 => { :metadata_key=>nil },
|
|
104
|
+
1 => { metadata_key1: :metadata_object1 }
|
|
105
|
+
}
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context 'when the dictionary_id is valid' do
|
|
109
|
+
before do
|
|
110
|
+
allow(subject).to receive(:dictionary_id!).and_return(0)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'initializes the metadata associated with the dictionary id for the given metadata_key' do
|
|
114
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to eq dictionary_metadata.dig(0, metadata_key)
|
|
115
|
+
subject.init(metadata_key: metadata_key)
|
|
116
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to be_nil
|
|
117
|
+
expect(dictionary_metadata).to eq expected_dictionary_metadata
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it_behaves_like 'the dictionary_metadata object reference has not changed' do
|
|
121
|
+
let(:expected_dictionary_metadata) { dictionary_metadata }
|
|
122
|
+
let(:actual_dictionary_metadata) { subject.dictionary_metadata }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it_behaves_like 'the dictionary_cache object reference has not changed' do
|
|
126
|
+
let(:expected_dictionary_cache) { dictionary_cache }
|
|
127
|
+
let(:actual_dictionary_cache) { subject.dictionary_cache_service.dictionary_cache }
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
context 'when the dictionary_id is INVALID' do
|
|
132
|
+
it 'raises an error' do
|
|
133
|
+
expect { subject.init(metadata_key: metadata_key) }.to raise_error "A dictionary id could not be found for key '#{key}'."
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
#dictionary_metadata?
|
|
139
|
+
describe '#dictionary_metadata?' do
|
|
140
|
+
before do
|
|
141
|
+
allow(subject).to receive(:dictionary_id).and_return(0)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
context 'when there is dictionary metadata associated with the dictionary for the metadata_key' do
|
|
145
|
+
it 'returns true' do
|
|
146
|
+
expect(subject.dictionary_metadata?(metadata_key: metadata_key)).to eq true
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
context 'when there is NO dictionary metadata associated with the dictionary for the metadata_key' do
|
|
151
|
+
context 'when there is no dictionary metadata for the dictionary_id' do
|
|
152
|
+
let(:dictionary_metadata) do
|
|
153
|
+
{
|
|
154
|
+
99 => { metadata_key => :metadata_object }
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'returns false' do
|
|
159
|
+
expect(subject.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
context 'when there is no dictionary metadata for the metadata_key' do
|
|
164
|
+
let(:dictionary_metadata) do
|
|
165
|
+
{
|
|
166
|
+
0 => { :wrong_metadata_key => :metadata_object }
|
|
167
|
+
}
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'returns false' do
|
|
171
|
+
expect(subject.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context 'when the dictionary metadata for the metadata_key is not present' do
|
|
176
|
+
let(:dictionary_metadata) do
|
|
177
|
+
{
|
|
178
|
+
0 => { metadata_key => nil }
|
|
179
|
+
}
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'returns false' do
|
|
183
|
+
expect(subject.dictionary_metadata?(metadata_key: metadata_key)).to eq false
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
#get_dictionary_metadata
|
|
190
|
+
describe '#get_dictionary_metadata' do
|
|
191
|
+
before do
|
|
192
|
+
allow(subject).to receive(:dictionary_id!).and_return(0)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
context 'when there is no dictionary_id found in the dictionary metadata associated with the dictionary key' do
|
|
196
|
+
before do
|
|
197
|
+
allow(subject).to receive(:dictionary_id!).and_call_original
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it 'raises an error' do
|
|
201
|
+
expect { subject.get_dictionary_metadata(metadata_key: metadata_key) }.to raise_error "A dictionary id could not be found for key '#{key}'."
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context 'when there is dictionary metadata associated with the dictionary for the metadata_key' do
|
|
206
|
+
it 'returns true' do
|
|
207
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to eq :metadata_object0
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
context 'when there is NO dictionary metadata associated with the dictionary for the metadata_key' do
|
|
212
|
+
context 'when there is no dictionary metadata for the dictionary_id' do
|
|
213
|
+
let(:dictionary_metadata) do
|
|
214
|
+
{
|
|
215
|
+
99 => { metadata_key => :metadata_object0 }
|
|
216
|
+
}
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'returns false' do
|
|
220
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to eq nil
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'when there is no dictionary metadata for the metadata_key' do
|
|
225
|
+
let(:dictionary_metadata) do
|
|
226
|
+
{
|
|
227
|
+
0 => { :wrong_metadata_key => :metadata_object0 }
|
|
228
|
+
}
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it 'returns false' do
|
|
232
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to eq nil
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
context 'when the dictionary metadata for the metadata_key is not present' do
|
|
237
|
+
let(:dictionary_metadata) do
|
|
238
|
+
{
|
|
239
|
+
0 => { metadata_key => nil }
|
|
240
|
+
}
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it 'returns false' do
|
|
244
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to eq nil
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
#set_dictionary_metadata
|
|
251
|
+
describe '#set_dictionary_metadata' do
|
|
252
|
+
before do
|
|
253
|
+
allow(subject).to receive(:dictionary_id!).and_return(0)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
let(:new_metadata_object) { :new_metadata_object0 }
|
|
257
|
+
|
|
258
|
+
context 'when passing valid arguments' do
|
|
259
|
+
it 'returns self' do
|
|
260
|
+
expect(subject.set_dictionary_metadata(value: new_metadata_object, metadata_key: metadata_key)).to be subject
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it 'sets the dictionary metadata value' do
|
|
264
|
+
subject.set_dictionary_metadata(value: new_metadata_object, metadata_key: metadata_key)
|
|
265
|
+
expect(subject.get_dictionary_metadata(metadata_key: metadata_key)).to eq new_metadata_object
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
context 'when there is no dictionary_id found in the dictionary metadata associated with the dictionary key' do
|
|
270
|
+
before do
|
|
271
|
+
allow(subject).to receive(:dictionary_id!).and_call_original
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it 'raises an error' do
|
|
275
|
+
expect { subject.get_dictionary_metadata(metadata_key: metadata_key) }.to raise_error "A dictionary id could not be found for key '#{key}'."
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|