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,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Preprocessors::WordPreprocessorValidatable, type: :module do
|
|
6
|
+
subject { MockSubject.new }
|
|
7
|
+
|
|
8
|
+
WordPreprocessorValidatable = described_class
|
|
9
|
+
|
|
10
|
+
class MockSubject
|
|
11
|
+
include WordPreprocessorValidatable
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class MockWordPreprocessor < LittleWeasel::Preprocessors::WordPreprocessor
|
|
15
|
+
def preprocess(word)
|
|
16
|
+
[true, "#{word}-preprocessed"]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:order) { 0 }
|
|
21
|
+
let(:preprocessor_on) { true }
|
|
22
|
+
let(:word_preprocessor) do
|
|
23
|
+
word_preprocessor = MockWordPreprocessor.new order: order
|
|
24
|
+
word_preprocessor.preprocessor_on = preprocessor_on
|
|
25
|
+
word_preprocessor
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
shared_examples 'an instance method is missing' do
|
|
29
|
+
before do
|
|
30
|
+
allow(word_preprocessor).to receive(:respond_to?).with(method).and_return(false)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'raises an error' do
|
|
34
|
+
expect { WordPreprocessorValidatable.validate_word_preprocessor word_preprocessor: word_preprocessor }.to raise_error expected_error_message
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
shared_examples 'a class method is missing' do
|
|
39
|
+
before do
|
|
40
|
+
allow(word_preprocessor.class).to receive(:respond_to?).with(method).and_return(false)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'raises an error' do
|
|
44
|
+
expect { WordPreprocessorValidatable.validate_word_preprocessor word_preprocessor: word_preprocessor }.to raise_error expected_error_message
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#.validate_word_preprocessor
|
|
49
|
+
describe '.validate_word_preprocessor' do
|
|
50
|
+
before do
|
|
51
|
+
allow(word_preprocessor.class).to receive(:respond_to?).and_call_original
|
|
52
|
+
allow(word_preprocessor).to receive(:respond_to?).and_call_original
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context 'when the object quacks right' do
|
|
56
|
+
it 'passes validation' do
|
|
57
|
+
expect { WordPreprocessorValidatable.validate_word_preprocessor word_preprocessor: word_preprocessor }.to_not raise_error
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context 'when the object DOES NOT quack right' do
|
|
62
|
+
let(:expected_error_message) { /Argument word_preprocessor: does not respond to/ }
|
|
63
|
+
|
|
64
|
+
context 'when a class method is missing' do
|
|
65
|
+
context 'when the class does not respond to .preprocess' do
|
|
66
|
+
let(:method) { :preprocess }
|
|
67
|
+
it_behaves_like 'a class method is missing'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'when the class does not respond to .preprocess?' do
|
|
71
|
+
let(:method) { :preprocess? }
|
|
72
|
+
it_behaves_like 'a class method is missing'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context 'when an instance method is missing' do
|
|
77
|
+
context 'when the object does not respond to #preprocess' do
|
|
78
|
+
let(:method) { :preprocess }
|
|
79
|
+
it_behaves_like 'an instance method is missing'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context 'when the object does not respond to #preprocess?' do
|
|
83
|
+
let(:method) { :preprocess? }
|
|
84
|
+
it_behaves_like 'an instance method is missing'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'when the object does not respond to #preprocessor_off?' do
|
|
88
|
+
let(:method) { :preprocessor_off? }
|
|
89
|
+
it_behaves_like 'an instance method is missing'
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
context 'when the object does not respond to #preprocessor_on' do
|
|
93
|
+
let(:method) { :preprocessor_on }
|
|
94
|
+
it_behaves_like 'an instance method is missing'
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'when the object does not respond to #preprocessor_on=' do
|
|
98
|
+
let(:method) { :preprocessor_on= }
|
|
99
|
+
it_behaves_like 'an instance method is missing'
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
context 'when the object does not respond to #preprocessor_on?' do
|
|
103
|
+
let(:method) { :preprocessor_on? }
|
|
104
|
+
it_behaves_like 'an instance method is missing'
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Preprocessors::WordPreprocessorsValidatable, type: :module do
|
|
6
|
+
subject { MockSubject.new }
|
|
7
|
+
|
|
8
|
+
WordPreprocessorsValidatable = described_class
|
|
9
|
+
|
|
10
|
+
class MockSubject
|
|
11
|
+
include WordPreprocessorsValidatable
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
subject { MockSubject.new }
|
|
15
|
+
|
|
16
|
+
class MockWordPreprocessor < LittleWeasel::Preprocessors::WordPreprocessor
|
|
17
|
+
def initialize(order: 0)
|
|
18
|
+
super order: order
|
|
19
|
+
self.preprocessor_on = preprocessor_on
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def preprocess(word) [true, "#{word}-0"]; end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
#.validate_word_preprocessors
|
|
28
|
+
describe '.validate_word_preprocessors' do
|
|
29
|
+
context 'when passing a blank Array' do
|
|
30
|
+
it 'passes validaton' do
|
|
31
|
+
expect { WordPreprocessorsValidatable.validate_word_preprocessors(word_preprocessors: []) }.to_not raise_error
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context 'when passing a an Array with valid word preprocessors' do
|
|
36
|
+
it 'passes validation' do
|
|
37
|
+
expect { WordPreprocessorsValidatable.validate_word_preprocessors(word_preprocessors: [MockWordPreprocessor.new]) }.to_not raise_error
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'when passing an INVALID argument' do
|
|
42
|
+
context 'when passing an invalid Array' do
|
|
43
|
+
it 'raises an error' do
|
|
44
|
+
expect { WordPreprocessorsValidatable.validate_word_preprocessors(word_preprocessors: :not_an_array) }.to raise_error(/Argument word_preprocessors is not an Array/)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe LittleWeasel::Services::DictionaryCacheService do
|
|
6
|
+
include_context 'dictionary cache'
|
|
7
|
+
include_context 'dictionary keys'
|
|
8
|
+
include_context 'dictionary sourceable'
|
|
9
|
+
|
|
10
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache) }
|
|
11
|
+
|
|
12
|
+
let(:en_us_dictionary_key) { dictionary_key_for(language: :en, region: :us) }
|
|
13
|
+
let(:en_gb_dictionary_key) { dictionary_key_for(language: :en, region: :gb) }
|
|
14
|
+
let(:es_es_dictionary_key) { dictionary_key_for(language: :es, region: :es) }
|
|
15
|
+
|
|
16
|
+
let(:dictionary_key) { en_us_dictionary_key }
|
|
17
|
+
let(:key) { dictionary_key.key }
|
|
18
|
+
let(:file) { dictionary_path_for(file_name: key) }
|
|
19
|
+
let(:file_minus_ext) { key }
|
|
20
|
+
let(:dictionary_cache) { {} }
|
|
21
|
+
let!(:initialized_dictionary_cache) { LittleWeasel::Modules::DictionaryCacheKeys.initialize_dictionary_cache(dictionary_cache: {}) }
|
|
22
|
+
|
|
23
|
+
shared_examples 'the dictionary_cache object reference has not changed' do
|
|
24
|
+
it 'the dictionary_cache object has not changed' do
|
|
25
|
+
expect(actual_dictionary_cache).to eq expected_dictionary_cache
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe 'class methods' do
|
|
30
|
+
#.init
|
|
31
|
+
describe '.init' do
|
|
32
|
+
subject! { create(:dictionary_cache_service, dictionary_file_source: true, dictionary_cache: dictionary_cache) }
|
|
33
|
+
|
|
34
|
+
before do
|
|
35
|
+
create(:dictionary_cache_service, dictionary_file_source: true, dictionary_cache: dictionary_cache, dictionary_key: en_gb_dictionary_key)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'resets the cache to an initiaized state for all keys in the cache' do
|
|
39
|
+
expect { described_class.init(dictionary_cache: dictionary_cache) }.to change { dictionary_cache }.to(initialized_dictionary_cache)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'maintains dictionary_cache object integrity' do
|
|
43
|
+
it_behaves_like 'the dictionary_cache object reference has not changed' do
|
|
44
|
+
before { subject }
|
|
45
|
+
let(:actual_dictionary_cache) { described_class.init(dictionary_cache: dictionary_cache) }
|
|
46
|
+
let(:expected_dictionary_cache) { dictionary_cache }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
#.init?
|
|
52
|
+
describe '.init?' do
|
|
53
|
+
context 'when passing an initialized dictionary cache Hash' do
|
|
54
|
+
it 'returns true' do
|
|
55
|
+
expect(described_class.init? dictionary_cache: initialized_dictionary_cache).to eq true
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context 'when passing a NON-initialized dictionary cache Hash' do
|
|
60
|
+
before do
|
|
61
|
+
subject.add_dictionary_source source: file
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'returns false' do
|
|
65
|
+
expect(described_class.init? dictionary_cache: dictionary_cache).to eq false
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
#.count
|
|
71
|
+
describe '.count' do
|
|
72
|
+
context 'when there are no dictionary references' do
|
|
73
|
+
subject { create(:dictionary_cache_service) }
|
|
74
|
+
|
|
75
|
+
it 'returns 0' do
|
|
76
|
+
expect(described_class.count(dictionary_cache: subject.dictionary_cache)).to eq 0
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context 'when there are are dictionary references' do
|
|
81
|
+
subject { create(:dictionary_cache_service, dictionary_file_source: true) }
|
|
82
|
+
|
|
83
|
+
it 'returns the dictionary reference count' do
|
|
84
|
+
expect(described_class.count(dictionary_cache: subject.dictionary_cache)).to eq 1
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#init
|
|
91
|
+
describe '#init' do
|
|
92
|
+
subject! { create(:dictionary_cache_service, dictionary_file_source: true, dictionary_cache: dictionary_cache) }
|
|
93
|
+
|
|
94
|
+
let!(:subject2) { create(:dictionary_cache_service, dictionary_file_source: true, dictionary_cache: dictionary_cache, dictionary_key: en_gb_dictionary_key) }
|
|
95
|
+
let!(:original_dictionary_cache) { dictionary_cache }
|
|
96
|
+
|
|
97
|
+
it 'resets the cache to an initiaized state for the GIVEN KEY ONLY' do
|
|
98
|
+
expect { subject.init }.to change { dictionary_cache }.from(original_dictionary_cache).to(subject2.dictionary_cache)
|
|
99
|
+
expect { subject2.init }.to change { dictionary_cache }.from(original_dictionary_cache).to(subject.dictionary_cache)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe 'maintains dictionary_cache object integrity' do
|
|
103
|
+
it_behaves_like 'the dictionary_cache object reference has not changed' do
|
|
104
|
+
let(:actual_dictionary_cache) { subject.init.dictionary_cache }
|
|
105
|
+
let(:expected_dictionary_cache) { dictionary_cache }
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#dictionary_reference?
|
|
111
|
+
describe '#dictionary_reference?' do
|
|
112
|
+
subject { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_file_source: true, dictionary_cache: dictionary_cache) }
|
|
113
|
+
|
|
114
|
+
context 'when the dictionary reference exists' do
|
|
115
|
+
it 'returns true' do
|
|
116
|
+
expect(subject.dictionary_reference?).to eq true
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'when the dictionary reference DOES NOT exist' do
|
|
121
|
+
subject { create(:dictionary_cache_service, dictionary_key: es_es_dictionary_key, dictionary_cache: dictionary_cache) }
|
|
122
|
+
|
|
123
|
+
before do
|
|
124
|
+
create(:dictionary_cache_service, dictionary_key: en_us_dictionary_key, dictionary_cache: dictionary_cache)
|
|
125
|
+
.add_dictionary_source source: memory_source
|
|
126
|
+
create(:dictionary_cache_service, dictionary_key: en_gb_dictionary_key, dictionary_cache: dictionary_cache)
|
|
127
|
+
.add_dictionary_source source: dictionary_path_for(file_name: en_gb_dictionary_key.key)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'returns false' do
|
|
131
|
+
expect(subject.dictionary_reference?).to eq false
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe 'maintains dictionary_cache object integrity' do
|
|
136
|
+
it_behaves_like 'the dictionary_cache object reference has not changed' do
|
|
137
|
+
let(:actual_dictionary_cache) { subject.dictionary_cache }
|
|
138
|
+
let(:expected_dictionary_cache) { dictionary_cache }
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#add_dictionary_source source: memory_source
|
|
144
|
+
describe '#add_dictionary_source source: memory_source' do
|
|
145
|
+
subject! do
|
|
146
|
+
create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key)
|
|
147
|
+
.add_dictionary_source source: memory_source
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
context 'when a dictionary already exists' do
|
|
151
|
+
it 'raises an error' do
|
|
152
|
+
expect do
|
|
153
|
+
create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: subject.dictionary_cache)
|
|
154
|
+
.add_dictionary_source source: memory_source
|
|
155
|
+
end.to raise_error "The dictionary source associated with key '#{key}' already exists."
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
context 'when a dictionary reference for the key DOES NOT already exist' do
|
|
160
|
+
let(:dictionary_cache_service) do
|
|
161
|
+
create(:dictionary_cache_service, dictionary_key: en_gb_dictionary_key, dictionary_cache: subject.dictionary_cache)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
before do
|
|
165
|
+
dictionary_cache_service.add_dictionary_source source: memory_source
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
let(:dictionary_source) { dictionary_cache_service.dictionary_source }
|
|
169
|
+
|
|
170
|
+
it 'creates a new dictionary reference' do
|
|
171
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq true
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'creates a unique memory source' do
|
|
175
|
+
expect(LittleWeasel::Modules::DictionarySourceable.memory_source? dictionary_source).to be_truthy
|
|
176
|
+
expect(dictionary_source == subject.dictionary_source).to_not eq true
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
describe 'maintains dictionary_cache object integrity' do
|
|
181
|
+
it_behaves_like 'the dictionary_cache object reference has not changed' do
|
|
182
|
+
subject { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache) }
|
|
183
|
+
let(:actual_dictionary_cache) { subject.add_dictionary_source(source: memory_source).dictionary_cache }
|
|
184
|
+
let(:expected_dictionary_cache) { dictionary_cache }
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
#add_dictionary_source
|
|
190
|
+
describe '#add_dictionary_source' do
|
|
191
|
+
context 'when a dictionary reference for the key already exists' do
|
|
192
|
+
before do
|
|
193
|
+
create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key)
|
|
194
|
+
.add_dictionary_source(source: file)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it 'raises an error' do
|
|
198
|
+
expect do
|
|
199
|
+
create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key, dictionary_cache: subject.dictionary_cache)
|
|
200
|
+
.add_dictionary_source(source: file)
|
|
201
|
+
end.to raise_error "The dictionary source associated with key '#{key}' already exists."
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context 'when a dictionary reference for the key DOES NOT already exist' do
|
|
206
|
+
subject! do
|
|
207
|
+
create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key)
|
|
208
|
+
.add_dictionary_source(source: file)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
let(:en_gb_file) do
|
|
212
|
+
"#{ dictionary_path_for(file_name: en_gb_dictionary_key.key) }"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'creates a new dictionary reference' do
|
|
216
|
+
dictionary_cache_service = create(:dictionary_cache_service, dictionary_key: en_gb_dictionary_key, dictionary_cache: subject.dictionary_cache)
|
|
217
|
+
dictionary_cache_service.add_dictionary_source source: en_gb_file
|
|
218
|
+
expect(dictionary_cache_service.dictionary_reference?).to eq true
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
context 'when the file source already exists' do
|
|
222
|
+
it 'reuses the existing file source' do
|
|
223
|
+
dictionary_cache_service = create(:dictionary_cache_service, dictionary_key: en_gb_dictionary_key, dictionary_cache: subject.dictionary_cache)
|
|
224
|
+
# Note: We're using the same file as en-US dictionary key, so
|
|
225
|
+
# the file source is NOT unique and will be reused.
|
|
226
|
+
dictionary_cache_service.add_dictionary_source source: file
|
|
227
|
+
expect(LittleWeasel::Modules::DictionarySourceable.file_source? dictionary_cache_service.dictionary_source).to be_truthy
|
|
228
|
+
expect(dictionary_cache_service.dictionary_source == subject.dictionary_source).to eq true
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'when the file source DOES NOT already exists' do
|
|
233
|
+
it 'creates a unique file source' do
|
|
234
|
+
dictionary_cache_service = create(:dictionary_cache_service, dictionary_key: en_gb_dictionary_key, dictionary_cache: subject.dictionary_cache)
|
|
235
|
+
# Note: We're using file that is DIFFERENT from the file being used by the
|
|
236
|
+
# en-US dictionary key, the file source created will be unique.
|
|
237
|
+
dictionary_cache_service.add_dictionary_source source: en_gb_file
|
|
238
|
+
expect(LittleWeasel::Modules::DictionarySourceable.file_source? dictionary_cache_service.dictionary_source).to be_truthy
|
|
239
|
+
expect(dictionary_cache_service.dictionary_source == subject.dictionary_source).to eq false
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
describe 'maintains dictionary_cache object integrity' do
|
|
245
|
+
it_behaves_like 'the dictionary_cache object reference has not changed' do
|
|
246
|
+
subject { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache) }
|
|
247
|
+
let(:actual_dictionary_cache) { subject.add_dictionary_source(source: file).dictionary_cache }
|
|
248
|
+
let(:expected_dictionary_cache) { dictionary_cache }
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
#dictionary_file
|
|
254
|
+
describe '#dictionary_file' do
|
|
255
|
+
context 'when a file source is used' do
|
|
256
|
+
subject! { create(:dictionary_cache_service, dictionary_key: dictionary_key).add_dictionary_source(source: file) }
|
|
257
|
+
|
|
258
|
+
it 'returns the dictionary file' do
|
|
259
|
+
expect(subject.dictionary_file).to eq file
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
context 'when a memory source is used' do
|
|
264
|
+
subject! { create(:dictionary_cache_service, dictionary_key: dictionary_key).add_dictionary_source source: memory_source }
|
|
265
|
+
|
|
266
|
+
let(:dictionary_words) { dictionary_words_for(dictionary_file_path: file) }
|
|
267
|
+
|
|
268
|
+
it 'returns the dictionary file' do
|
|
269
|
+
expect(LittleWeasel::Modules::DictionarySourceable.memory_source? subject.dictionary_file).to be_truthy
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
#dictionary_id
|
|
275
|
+
describe '#dictionary_id' do
|
|
276
|
+
context 'when a dictionary id exists for the given dictionary key' do
|
|
277
|
+
before do
|
|
278
|
+
subject.add_dictionary_source source: memory_source
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it 'returns the key' do
|
|
282
|
+
expect(subject.dictionary_id).to_not be_nil
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
context 'when a dictionary id DOES NOT exist for the given dictionary key' do
|
|
287
|
+
it 'returns nil' do
|
|
288
|
+
expect(subject.dictionary_id).to be_nil
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
#dictionary_id!
|
|
294
|
+
describe '#dictionary_id!' do
|
|
295
|
+
context 'when a dictionary id associated with the dictionary key exists' do
|
|
296
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key, dictionary_file_source: true) }
|
|
297
|
+
|
|
298
|
+
it 'returns the dictionary id' do
|
|
299
|
+
expect { subject.dictionary_id! }.to_not raise_error
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
context 'when a dictionary id associated with the dictionary key DOES NOT exist' do
|
|
304
|
+
subject { create(:dictionary_cache_service) }
|
|
305
|
+
|
|
306
|
+
it 'raises an error' do
|
|
307
|
+
expect { subject.dictionary_id! }.to raise_error "A dictionary id could not be found for key '#{key}'."
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
#dictionary_exists?
|
|
313
|
+
describe '#dictionary_exists?' do
|
|
314
|
+
context 'when the dictionary reference does not exist' do
|
|
315
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache) }
|
|
316
|
+
|
|
317
|
+
it 'returns false' do
|
|
318
|
+
expect(subject.dictionary_exists?).to eq false
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context 'when the dictionary is already loaded' do
|
|
323
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_file_source: true, load: true) }
|
|
324
|
+
|
|
325
|
+
it 'returns true' do
|
|
326
|
+
expect(subject.dictionary_exists?).to eq true
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
context 'when the dictionary is NOT already loaded' do
|
|
331
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_file_source: true) }
|
|
332
|
+
|
|
333
|
+
it 'returns false' do
|
|
334
|
+
expect(subject.dictionary_exists?).to eq false
|
|
335
|
+
end
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
#dictionary_object
|
|
340
|
+
describe '#dictionary_object' do
|
|
341
|
+
context 'when the dictionary object is already cached/loaded' do
|
|
342
|
+
subject { create(:dictionary_cache_service, dictionary_file_source: true, load: true) }
|
|
343
|
+
|
|
344
|
+
it 'returns the dictionary object' do
|
|
345
|
+
expect(subject.dictionary_object).to be_kind_of LittleWeasel::Dictionary
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context 'when the dictionary object is NOT already cached/loaded' do
|
|
350
|
+
context 'when the dictionary reference exists' do
|
|
351
|
+
it 'returns an object that is not present?' do
|
|
352
|
+
expect(create(:dictionary_cache_service, dictionary_file_source: true).dictionary_object).to_not be_present
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
context 'when the dictionary reference DOES NOT exist' do
|
|
357
|
+
it 'returns an object that is not present?' do
|
|
358
|
+
expect(create(:dictionary_cache_service).dictionary_object).to_not be_present
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
#dictionary_object!
|
|
365
|
+
describe '#dictionary_object!' do
|
|
366
|
+
describe 'when the dictionary is NOT in the cache' do
|
|
367
|
+
it 'raises an error' do
|
|
368
|
+
expect { subject.dictionary_object! }.to raise_error("The dictionary object associated with argument key '#{key}' is not in the cache.")
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
describe 'when the dictionary is loaded/cached' do
|
|
373
|
+
subject { create(:dictionary_cache_service, dictionary_file_source: true, load: true) }
|
|
374
|
+
|
|
375
|
+
it 'returns the dictionary cache for the dictionary' do
|
|
376
|
+
expect(subject.dictionary_reference?).to eq true
|
|
377
|
+
expect(subject.dictionary_exists?).to eq true
|
|
378
|
+
expect(subject.dictionary_object!).to be_kind_of LittleWeasel::Dictionary
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
#dictionary_object=
|
|
384
|
+
describe '#dictionary_object=' do
|
|
385
|
+
context 'when the dictionary object passed is invalid' do
|
|
386
|
+
subject { create(:dictionary_cache_service) }
|
|
387
|
+
|
|
388
|
+
context 'when nil' do
|
|
389
|
+
it 'raises an error' do
|
|
390
|
+
expect { subject.dictionary_object = nil }.to raise_error 'Argument object is not a Dictionary object'
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
context 'when not a Dictionary object' do
|
|
395
|
+
it 'raises an error' do
|
|
396
|
+
expect { subject.dictionary_object = :wrong_object }.to raise_error 'Argument object is not a Dictionary object'
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
context 'when there is NO dictionary reference' do
|
|
402
|
+
before do
|
|
403
|
+
allow(dictionary_object).to receive(:is_a?).and_return(true)
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key) }
|
|
407
|
+
|
|
408
|
+
let(:dictionary_object) { Object.new }
|
|
409
|
+
|
|
410
|
+
it 'raises an error' do
|
|
411
|
+
expect { subject.dictionary_object = dictionary_object }.to raise_error "The dictionary reference associated with key '#{key}' could not be found."
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
context 'when the dictionary is already loaded/cached and different from the dictionary object passed' do
|
|
416
|
+
subject { create(:dictionary_cache_service, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key, dictionary_file_source: true, load: true) }
|
|
417
|
+
|
|
418
|
+
let(:dictionary) { create(:dictionary, dictionary_cache: dictionary_cache, dictionary_key: dictionary_key) }
|
|
419
|
+
|
|
420
|
+
it 'raises an error' do
|
|
421
|
+
expect { subject.dictionary_object = dictionary }.to raise_error "The dictionary is already loaded/cached for key '#{key}'; use #unload or #kill first."
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
context 'when the dictionary is already loaded/cached and the dictionary object is the same as the one that is loaded/cached' do
|
|
426
|
+
subject { create(:dictionary_cache_service, dictionary_file_source: true, load: true) }
|
|
427
|
+
|
|
428
|
+
it 'returns the same object' do
|
|
429
|
+
expect(subject.dictionary_object = subject.dictionary_object).to eq subject.dictionary_object
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
context 'when the dictionary is NOT already loaded/cached' do
|
|
434
|
+
subject { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: true) }
|
|
435
|
+
|
|
436
|
+
let(:dictionary) { create(:dictionary, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache) }
|
|
437
|
+
|
|
438
|
+
it 'updates the dictionary object' do
|
|
439
|
+
expect { subject.dictionary_object = dictionary }.to_not raise_error
|
|
440
|
+
expect(subject.dictionary_object).to eq dictionary
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
end
|