LittleWeasel 3.0.3 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.reek.yml +17 -0
  4. data/.rspec +4 -2
  5. data/.rubocop.yml +187 -0
  6. data/.ruby-version +1 -1
  7. data/.yardopts +2 -0
  8. data/CHANGELOG.md +22 -1
  9. data/Gemfile +3 -1
  10. data/Jenkinsfile +20 -0
  11. data/LittleWeasel.gemspec +31 -18
  12. data/README.md +408 -42
  13. data/Rakefile +296 -3
  14. data/lib/LittleWeasel/block_results.rb +81 -0
  15. data/lib/LittleWeasel/configure.rb +98 -0
  16. data/lib/LittleWeasel/dictionary.rb +125 -0
  17. data/lib/LittleWeasel/dictionary_key.rb +48 -0
  18. data/lib/LittleWeasel/dictionary_manager.rb +91 -0
  19. data/lib/LittleWeasel/errors/dictionary_file_already_loaded_error.rb +9 -0
  20. data/lib/LittleWeasel/errors/dictionary_file_empty_error.rb +8 -0
  21. data/lib/LittleWeasel/errors/dictionary_file_not_found_error.rb +8 -0
  22. data/lib/LittleWeasel/errors/dictionary_file_too_large_error.rb +16 -0
  23. data/lib/LittleWeasel/errors/language_required_error.rb +8 -0
  24. data/lib/LittleWeasel/errors/must_override_error.rb +8 -0
  25. data/lib/LittleWeasel/filters/en_us/currency_filter.rb +19 -0
  26. data/lib/LittleWeasel/filters/en_us/numeric_filter.rb +19 -0
  27. data/lib/LittleWeasel/filters/en_us/single_character_word_filter.rb +21 -0
  28. data/lib/LittleWeasel/filters/word_filter.rb +59 -0
  29. data/lib/LittleWeasel/filters/word_filter_managable.rb +80 -0
  30. data/lib/LittleWeasel/filters/word_filter_validatable.rb +31 -0
  31. data/lib/LittleWeasel/filters/word_filterable.rb +19 -0
  32. data/lib/LittleWeasel/filters/word_filters_validatable.rb +29 -0
  33. data/lib/LittleWeasel/metadata/dictionary_metadata.rb +145 -0
  34. data/lib/LittleWeasel/metadata/invalid_words_metadata.rb +134 -0
  35. data/lib/LittleWeasel/metadata/invalid_words_service_results.rb +45 -0
  36. data/lib/LittleWeasel/metadata/metadata_observable_validatable.rb +22 -0
  37. data/lib/LittleWeasel/metadata/metadata_observerable.rb +90 -0
  38. data/lib/LittleWeasel/metadata/metadatable.rb +134 -0
  39. data/lib/LittleWeasel/modules/class_name_to_symbol.rb +26 -0
  40. data/lib/LittleWeasel/modules/configurable.rb +26 -0
  41. data/lib/LittleWeasel/modules/deep_dup.rb +11 -0
  42. data/lib/LittleWeasel/modules/dictionary_cache_keys.rb +34 -0
  43. data/lib/LittleWeasel/modules/dictionary_cache_servicable.rb +26 -0
  44. data/lib/LittleWeasel/modules/dictionary_cache_validatable.rb +18 -0
  45. data/lib/LittleWeasel/modules/dictionary_creator_servicable.rb +27 -0
  46. data/lib/LittleWeasel/modules/dictionary_file_loader.rb +67 -0
  47. data/lib/LittleWeasel/modules/dictionary_key_validatable.rb +17 -0
  48. data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
  49. data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
  50. data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +15 -0
  51. data/lib/LittleWeasel/modules/dictionary_source_validatable.rb +15 -0
  52. data/lib/LittleWeasel/modules/dictionary_sourceable.rb +86 -0
  53. data/lib/LittleWeasel/modules/dictionary_validatable.rb +18 -0
  54. data/lib/LittleWeasel/modules/language.rb +24 -0
  55. data/lib/LittleWeasel/modules/language_validatable.rb +14 -0
  56. data/lib/LittleWeasel/modules/locale.rb +23 -0
  57. data/lib/LittleWeasel/modules/order_validatable.rb +16 -0
  58. data/lib/LittleWeasel/modules/orderable.rb +17 -0
  59. data/lib/LittleWeasel/modules/region.rb +24 -0
  60. data/lib/LittleWeasel/modules/region_validatable.rb +14 -0
  61. data/lib/LittleWeasel/modules/tag_validatable.rb +14 -0
  62. data/lib/LittleWeasel/modules/taggable.rb +31 -0
  63. data/lib/LittleWeasel/modules/word_results_validatable.rb +28 -0
  64. data/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor.rb +22 -0
  65. data/lib/LittleWeasel/preprocessors/preprocessed_word.rb +29 -0
  66. data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +56 -0
  67. data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +59 -0
  68. data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +28 -0
  69. data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
  70. data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +123 -0
  71. data/lib/LittleWeasel/preprocessors/word_preprocessor_managable.rb +114 -0
  72. data/lib/LittleWeasel/preprocessors/word_preprocessor_validatable.rb +40 -0
  73. data/lib/LittleWeasel/preprocessors/word_preprocessors_validatable.rb +24 -0
  74. data/lib/LittleWeasel/services/dictionary_cache_service.rb +211 -0
  75. data/lib/LittleWeasel/services/dictionary_creator_service.rb +94 -0
  76. data/lib/LittleWeasel/services/dictionary_file_loader_service.rb +37 -0
  77. data/lib/LittleWeasel/services/dictionary_killer_service.rb +35 -0
  78. data/lib/LittleWeasel/services/dictionary_metadata_service.rb +116 -0
  79. data/lib/LittleWeasel/services/invalid_words_service.rb +59 -0
  80. data/lib/LittleWeasel/version.rb +3 -1
  81. data/lib/LittleWeasel/word_results.rb +146 -0
  82. data/lib/LittleWeasel.rb +5 -184
  83. data/spec/factories/dictionary.rb +43 -0
  84. data/spec/factories/dictionary_cache_service.rb +95 -0
  85. data/spec/factories/dictionary_creator_service.rb +16 -0
  86. data/spec/factories/dictionary_file_loader_service.rb +13 -0
  87. data/spec/factories/dictionary_hash.rb +39 -0
  88. data/spec/factories/dictionary_key.rb +14 -0
  89. data/spec/factories/dictionary_killer_service.rb +14 -0
  90. data/spec/factories/dictionary_manager.rb +10 -0
  91. data/spec/factories/dictionary_metadata.rb +16 -0
  92. data/spec/factories/dictionary_metadata_service.rb +16 -0
  93. data/spec/factories/numeric_filter.rb +12 -0
  94. data/spec/factories/preprocessed_word.rb +16 -0
  95. data/spec/factories/preprocessed_words.rb +41 -0
  96. data/spec/factories/single_character_word_filter.rb +12 -0
  97. data/spec/factories/word_results.rb +16 -0
  98. data/spec/lib/LittleWeasel/block_results_spec.rb +248 -0
  99. data/spec/lib/LittleWeasel/configure_spec.rb +74 -0
  100. data/spec/lib/LittleWeasel/dictionary_key_spec.rb +118 -0
  101. data/spec/lib/LittleWeasel/dictionary_manager_spec.rb +166 -0
  102. data/spec/lib/LittleWeasel/dictionary_spec.rb +289 -0
  103. data/spec/lib/LittleWeasel/filters/en_us/currency_filter_spec.rb +80 -0
  104. data/spec/lib/LittleWeasel/filters/en_us/numeric_filter_spec.rb +66 -0
  105. data/spec/lib/LittleWeasel/filters/en_us/single_character_word_filter_spec.rb +58 -0
  106. data/spec/lib/LittleWeasel/filters/word_filter_managable_spec.rb +180 -0
  107. data/spec/lib/LittleWeasel/filters/word_filter_spec.rb +151 -0
  108. data/spec/lib/LittleWeasel/filters/word_filter_validatable_spec.rb +94 -0
  109. data/spec/lib/LittleWeasel/filters/word_filters_validatable_spec.rb +48 -0
  110. data/spec/lib/LittleWeasel/integraton_tests/dictionary_integration_spec.rb +201 -0
  111. data/spec/lib/LittleWeasel/metadata/dictionary_creator_servicable_spec.rb +54 -0
  112. data/spec/lib/LittleWeasel/metadata/dictionary_metadata_spec.rb +209 -0
  113. data/spec/lib/LittleWeasel/metadata/invalid_words_metadata_spec.rb +155 -0
  114. data/spec/lib/LittleWeasel/metadata/metadata_observerable_spec.rb +31 -0
  115. data/spec/lib/LittleWeasel/metadata/metadatable_spec.rb +35 -0
  116. data/spec/lib/LittleWeasel/modules/class_name_to_symbol_spec.rb +21 -0
  117. data/spec/lib/LittleWeasel/modules/dictionary_file_loader_spec.rb +125 -0
  118. data/spec/lib/LittleWeasel/modules/dictionary_sourceable_spec.rb +81 -0
  119. data/spec/lib/LittleWeasel/modules/language_spec.rb +112 -0
  120. data/spec/lib/LittleWeasel/modules/locale_spec.rb +95 -0
  121. data/spec/lib/LittleWeasel/modules/region_spec.rb +112 -0
  122. data/spec/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor_spec.rb +34 -0
  123. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_spec.rb +105 -0
  124. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_validatable_spec.rb +143 -0
  125. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_spec.rb +77 -0
  126. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_validatable_spec.rb +58 -0
  127. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_managable_spec.rb +242 -0
  128. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +218 -0
  129. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_validatable_spec.rb +109 -0
  130. data/spec/lib/LittleWeasel/preprocessors/word_preprocessors_validatable_spec.rb +49 -0
  131. data/spec/lib/LittleWeasel/services/dictionary_cache_service_spec.rb +444 -0
  132. data/spec/lib/LittleWeasel/services/dictionary_creator_service_spec.rb +119 -0
  133. data/spec/lib/LittleWeasel/services/dictionary_file_loader_service_spec.rb +71 -0
  134. data/spec/lib/LittleWeasel/services/dictionary_metadata_service_spec.rb +279 -0
  135. data/spec/lib/LittleWeasel/word_results_spec.rb +275 -0
  136. data/spec/lib/LittleWeasel/workflow/workflow_spec.rb +20 -0
  137. data/spec/spec_helper.rb +117 -6
  138. data/spec/support/factory_bot.rb +15 -0
  139. data/spec/support/file_helpers.rb +46 -0
  140. data/spec/support/files/empty-dictionary.txt +0 -0
  141. data/{lib/dictionary → spec/support/files/en-US-big.txt} +262156 -31488
  142. data/spec/support/files/en-US-tagged.txt +26 -0
  143. data/spec/support/files/en-US.txt +26 -0
  144. data/spec/support/files/en.txt +26 -0
  145. data/spec/support/files/es-ES.txt +27 -0
  146. data/spec/support/files/es.txt +27 -0
  147. data/spec/support/general_helpers.rb +68 -0
  148. data/spec/support/shared_contexts.rb +107 -0
  149. data/spec/support/shared_examples.rb +105 -0
  150. metadata +378 -38
  151. data/spec/checker/checker_spec.rb +0 -286
@@ -0,0 +1,166 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::DictionaryManager do
6
+ include_context 'dictionary keys'
7
+
8
+ subject { create(:dictionary_manager) }
9
+
10
+ let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache)}
11
+ let(:dictionary_metadata_service) { create(:dictionary_metadata_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata)}
12
+ let(:dictionary_key) { create(:dictionary_key, language: language, region: region, tag: tag) }
13
+ let(:dictionary_cache) { subject.dictionary_cache }
14
+ let(:dictionary_metadata) { subject.dictionary_metadata }
15
+
16
+ let(:language) { :en }
17
+ let(:region) { :us }
18
+ let(:tag) {}
19
+ let(:file) { dictionary_path_for(file_name: dictionary_key.key) }
20
+
21
+ let(:metadata_key) do
22
+ dictionary_cache_service.dictionary_object.dictionary_metadata_object.observers.keys.first
23
+ end
24
+
25
+ before(:each) do
26
+ subject.init
27
+ end
28
+
29
+ #.new
30
+ describe '.new' do
31
+ it 'does not raise an error' do
32
+ expect { subject }.not_to raise_error
33
+ end
34
+ end
35
+
36
+ #dictionary_exist?
37
+ describe '#dictionary_exist?' do
38
+ let!(:expected_dictionary_object) do
39
+ subject.create_dictionary_from_memory(dictionary_key: dictionary_key,
40
+ dictionary_words: %w(My dictionary words) )
41
+ end
42
+
43
+ context 'when the dictionary exists' do
44
+ it 'returns true' do
45
+ expect(subject.dictionary_exist? dictionary_key: dictionary_key)
46
+ .to eq true
47
+ end
48
+ end
49
+
50
+ context 'when the dictionary DOES NOT exist' do
51
+ let(:en_gb_dictionary_key) { dictionary_key_for(language: :en, region: :gb) }
52
+
53
+ it 'returns false' do
54
+ expect(subject.dictionary_exist? dictionary_key: en_gb_dictionary_key)
55
+ .to eq false
56
+ end
57
+ end
58
+ end
59
+
60
+ #dictionary_for
61
+ describe '#dictionary_for' do
62
+ let!(:expected_dictionary_object) do
63
+ subject.create_dictionary_from_memory(dictionary_key: dictionary_key,
64
+ dictionary_words: %w(My dictionary words) )
65
+ end
66
+
67
+ context 'when the dictionary exists' do
68
+ it 'returns the dictionary object' do
69
+ expect(subject.dictionary_for dictionary_key: dictionary_key)
70
+ .to be expected_dictionary_object
71
+ end
72
+ end
73
+
74
+ context 'when the dictionary DOES NOT exist' do
75
+ let(:en_gb_dictionary_key) { dictionary_key_for(language: :en, region: :gb) }
76
+
77
+ it 'raises an error' do
78
+ expect { subject.dictionary_for dictionary_key: en_gb_dictionary_key }
79
+ .to raise_error("The dictionary object associated with argument key '#{en_gb_dictionary_key.key}' is not in the cache.")
80
+ end
81
+ end
82
+ end
83
+
84
+ #create_dictionary_from_file
85
+ describe '#create_dictionary_from_file' do
86
+ context 'when the dictionary DOES NOT exist' do
87
+ it 'creates a dictionary and returns a dictionary object' do
88
+ expect(subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)).to be_kind_of LittleWeasel::Dictionary
89
+ end
90
+ end
91
+
92
+ context 'when the dictionary already exists' do
93
+ before do
94
+ subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)
95
+ end
96
+
97
+ it 'raises an error' do
98
+ expect { subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file) }
99
+ .to raise_error("The dictionary source associated with key '#{dictionary_key.key}' already exists.")
100
+ end
101
+ end
102
+ end
103
+
104
+ #create_dictionary_from_memory
105
+ describe '#create_dictionary_from_memory' do
106
+ let(:dictionary_words) { dictionary_words_for(dictionary_file_path: file) }
107
+
108
+ context 'when the dictionary reference does not exist and the dictionary is not cached' do
109
+ it 'adds a dictionary reference caches the dictionary and returns a dictionary object' do
110
+ expect(subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words)).to be_kind_of LittleWeasel::Dictionary
111
+ expect(dictionary_cache_service.dictionary_reference?).to eq true
112
+ expect(dictionary_cache_service.dictionary_object?).to eq true
113
+ end
114
+ end
115
+
116
+ context 'when the dictionary reference exists' do
117
+ before do
118
+ subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words)
119
+ end
120
+
121
+ it 'raises an error' do
122
+ expect { subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: dictionary_words) }
123
+ .to raise_error "The dictionary source associated with key '#{dictionary_key.key}' already exists."
124
+ end
125
+ end
126
+ end
127
+
128
+ #kill
129
+ describe '#kill_dictionary' do
130
+ context 'dictionaries created from files' do
131
+ before do
132
+ subject.create_dictionary_from_file(dictionary_key: dictionary_key, file: file)
133
+ end
134
+
135
+ it 'removes the dictionary, file source reference and metadata from the dictionary cache' do
136
+ metadata_key # Capture this before we unload the dictionary
137
+ subject.kill_dictionary(dictionary_key: dictionary_key)
138
+ expect(dictionary_cache_service.dictionary_exist?).to eq false
139
+ expect(dictionary_cache_service.dictionary_reference?).to eq false
140
+ expect(dictionary_metadata_service.dictionary_metadata?(metadata_key: metadata_key)).to eq false
141
+ end
142
+
143
+ it 'returns the dictionary manager instance' do
144
+ expect(subject.kill_dictionary(dictionary_key: dictionary_key)).to eq subject
145
+ end
146
+ end
147
+
148
+ context 'dictionaries created from memory' do
149
+ before do
150
+ subject.create_dictionary_from_memory(dictionary_key: dictionary_key, dictionary_words: %w(Abel Cain Deborah Elijah))
151
+ end
152
+
153
+ it 'removes the dictionary, memory source reference and metadata from the dictionary cache' do
154
+ metadata_key # Capture this before we unload the dictionary
155
+ subject.kill_dictionary(dictionary_key: dictionary_key)
156
+ expect(dictionary_cache_service.dictionary_exist?).to eq false
157
+ expect(dictionary_cache_service.dictionary_reference?).to eq false
158
+ expect(dictionary_metadata_service.dictionary_metadata?(metadata_key: metadata_key)).to eq false
159
+ end
160
+
161
+ it 'returns the dictionary manager instance' do
162
+ expect(subject.kill_dictionary(dictionary_key: dictionary_key)).to eq subject
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,289 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Dictionary do
6
+ include_context 'dictionary keys'
7
+ include_context 'mock word filters'
8
+
9
+ DictionaryResultsHelpers = Support::GeneralHelpers::DictionaryResultsHelpers
10
+
11
+
12
+ subject { create(:dictionary, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_words: dictionary_words, word_filters: word_filters) }
13
+
14
+ before(:each) { LittleWeasel.configure { |config| config.reset } }
15
+ before { dictionary_cache_service }
16
+
17
+ let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: dictionary_key.key) }
18
+ let(:dictionary_key) { dictionary_key_for(language: :en, region: :us, tag: :big) }
19
+ let(:dictionary_cache) { {} }
20
+ let(:dictionary_metadata) { {} }
21
+ let(:dictionary_file_path) { dictionary_path_for(file_name: dictionary_key.key) }
22
+ let(:dictionary_words) { dictionary_words_for(dictionary_file_path: dictionary_file_path) }
23
+ let(:word_filters) {}
24
+
25
+ def block_results_include?(block_results, word)
26
+ word_results = block_results.word_results.find do |word_results|
27
+ word_results.original_word == word
28
+ end
29
+ [word_results.present?, word_results&.word_valid]
30
+ end
31
+
32
+ #.new
33
+ describe '.new' do
34
+ context 'with a valid dictionary words Array' do
35
+ it 'instantiates without error' do
36
+ expect { subject }.to_not raise_error
37
+ end
38
+ end
39
+
40
+ context 'with an invalid dictionary words Array' do
41
+ context 'when nil' do
42
+ let(:dictionary_words) {}
43
+
44
+ it 'raises an error' do
45
+ expect { subject }.to raise_error ArgumentError
46
+ end
47
+ end
48
+
49
+ context 'when not an Array' do
50
+ let(:dictionary_words) { :not_an_array }
51
+
52
+ it 'raises an error' do
53
+ expect { subject }.to raise_error ArgumentError
54
+ end
55
+ end
56
+ end
57
+
58
+ describe 'word_filter:' do
59
+ context 'when argument word_filters is nil' do
60
+ it 'no word filters will be used' do
61
+ expect(subject.word_filters).to be_blank
62
+ end
63
+ end
64
+
65
+ context 'when argument word_filters is an empty Array ([])' do
66
+ let(:word_filters) { [] }
67
+
68
+ it 'no word filters will be used' do
69
+ expect(subject.word_filters.count).to eq 0
70
+ end
71
+ end
72
+
73
+ context 'when argument word_filters is NOT nil' do
74
+ let(:word_filters) { [WordFilter01.new, WordFilter02.new] }
75
+
76
+ it 'the dictionary will use the word filters passed' do
77
+ expect(subject.word_filters.count).to eq 2
78
+ expect(subject.word_filters).to include(a_kind_of(WordFilter01))
79
+ expect(subject.word_filters).to include(a_kind_of(WordFilter02))
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ #.to_hash
86
+ describe '.to_hash' do
87
+ let(:expected_hash) do
88
+ {
89
+ 'this' => true,
90
+ 'is' => true,
91
+ 'a' => true,
92
+ 'test' => true
93
+ }
94
+ end
95
+
96
+ it 'returns a Hash of dictionary words' do
97
+ expect(described_class.to_hash(dictionary_words: %w(this is a test))).to eq expected_hash
98
+ end
99
+ end
100
+
101
+ #detached?
102
+ describe '#detached?' do
103
+ before do
104
+ subject
105
+ end
106
+
107
+ let(:dictionary_cache_service) { create(:dictionary_cache_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_file_source: dictionary_key.key, load: true) }
108
+
109
+ context 'when the dictionary object is in the dictionary cache' do
110
+ it 'returns false' do
111
+ dictionary_cache_service
112
+ expect(dictionary_cache_service.dictionary_object?).to eq true
113
+ expect(subject.detached?).to eq false
114
+ end
115
+ end
116
+
117
+ context 'when the dictionary object is NOT in the dictionary cache' do
118
+ before do
119
+ dictionary_cache_service
120
+ dictionary_killer_service = create(:dictionary_killer_service, dictionary_key: dictionary_key, dictionary_cache: dictionary_cache, dictionary_metadata: dictionary_metadata)
121
+ dictionary_killer_service.execute
122
+ end
123
+
124
+ it 'returns true' do
125
+ expect(dictionary_cache_service.dictionary_object?).to eq false
126
+ expect(subject.detached?).to eq true
127
+ end
128
+ end
129
+ end
130
+
131
+ #key
132
+ describe '#key' do
133
+ it 'returns the expected key' do
134
+ expect(subject.key).to eq dictionary_key.key
135
+ end
136
+ end
137
+
138
+ #count
139
+ describe '#count' do
140
+ before do
141
+ subject.word_results('badword')
142
+ end
143
+
144
+ it 'returns the count of all valid words' do
145
+ expect(subject.count).to eq dictionary_words.count
146
+ end
147
+ end
148
+
149
+ #count_all_words
150
+ describe '#count_all_words' do
151
+ before do
152
+ subject.word_results('badword')
153
+ end
154
+
155
+ it 'returns the count of all valid and invalid words' do
156
+ expect(subject.count_all_words).to eq dictionary_words.count + 1
157
+ end
158
+ end
159
+
160
+ #count_invalid_words
161
+ describe '#count_invalid_words' do
162
+ before do
163
+ subject.word_results('badword')
164
+ end
165
+
166
+ it 'returns the count of all invalid words' do
167
+ expect(subject.count_invalid_words).to eq 1
168
+ end
169
+ end
170
+
171
+ #word_results
172
+ describe '#word_results' do
173
+ context 'when argument word is INVALID' do
174
+ context 'when not a String' do
175
+ let(:word) { :not_a_string }
176
+
177
+ it 'raises an error' do
178
+ expect { subject.word_results(word) }.to raise_error "Argument word is not a String: #{word.class}"
179
+ end
180
+ end
181
+ end
182
+
183
+ context 'when searching for words in the dictionary' do
184
+ context 'when the word is found' do
185
+ it 'returns true' do
186
+ expect(subject.word_results('dog').success?).to eq true
187
+ end
188
+ end
189
+
190
+ context 'when the word is not found' do
191
+ it 'returns false' do
192
+ expect(subject.word_results('badword').success?).to eq false
193
+ end
194
+ end
195
+ end
196
+ end
197
+
198
+ #block_results
199
+ describe '#block_results' do
200
+ context 'when nil is passed' do
201
+ it 'raises an error' do
202
+ expect { subject.block_results nil }.to raise_error(/Argument word_block is not a String/)
203
+ end
204
+ end
205
+
206
+ context 'when an empty String is passed' do
207
+ it 'raises an error' do
208
+ expect { subject.block_results '' }.to raise_error(/Argument word_block is empty/)
209
+ end
210
+ end
211
+
212
+ context 'when a valid block of words is passed' do
213
+ subject do
214
+ create(:dictionary,
215
+ dictionary_key: dictionary_key,
216
+ dictionary_cache: dictionary_cache,
217
+ dictionary_words: dictionary_words,
218
+ word_filters: word_filters).block_results word_block
219
+ end
220
+
221
+ let(:word_filters) { [LittleWeasel::Filters::EnUs::NumericFilter.new] }
222
+ let(:word_block) do
223
+ "I'm older than you bubble-butt; I was born in 1964, before your time!"
224
+ end
225
+
226
+ it 'returns a WordResults object with the correct data about the words passed' do
227
+ DictionaryResultsHelpers.print_block_results word_block, subject
228
+
229
+ expect(subject.word_results.count).to eq 13
230
+ expect(block_results_include?(subject, "I'm")).to eq [true, true]
231
+ expect(block_results_include?(subject, 'older')).to eq [true, true]
232
+ expect(block_results_include?(subject, 'than')).to eq [true, true]
233
+ expect(block_results_include?(subject, 'you')).to eq [true, true]
234
+ expect(block_results_include?(subject, 'bubble-butt')).to eq [true, false]
235
+ expect(block_results_include?(subject, 'I')).to eq [true, true]
236
+ expect(block_results_include?(subject, 'was')).to eq [true, true]
237
+ expect(block_results_include?(subject, 'born')).to eq [true, true]
238
+ expect(block_results_include?(subject, 'in')).to eq [true, true]
239
+ expect(block_results_include?(subject, '1964')).to eq [true, false]
240
+ expect(block_results_include?(subject, 'before')).to eq [true, true]
241
+ expect(block_results_include?(subject, 'your')).to eq [true, true]
242
+ expect(block_results_include?(subject, 'time')).to eq [true, true]
243
+ end
244
+ end
245
+ end
246
+
247
+ # Configuration
248
+ context 'configuration options that alter behavior' do
249
+ context 'when max_invalid_words_bytesize? is true' do
250
+ context 'when a word is not found' do
251
+ context 'when the max_invalid_words_bytesize threashold has not been exceeded' do
252
+ it 'adds the word to the cache' do
253
+ expect { subject.word_results('badword') }.to change { subject.count_all_words }.by(1)
254
+ end
255
+ end
256
+
257
+ context 'when the max_invalid_words_bytesize threashold HAS been exceeded' do
258
+ before do
259
+ LittleWeasel.configure { |config| config.max_invalid_words_bytesize = 30 }
260
+ end
261
+
262
+ it 'does NOT add the word to the cache' do
263
+ expect do
264
+ subject.word_results('IWillBeCached01')
265
+ subject.word_results('IWillBeCached02')
266
+ subject.word_results('IWontBeCached01')
267
+ subject.word_results('IWontBeCached02')
268
+ end.to change { subject.count_all_words }.by(2)
269
+ end
270
+ end
271
+ end
272
+ end
273
+
274
+ context 'when max_invalid_words_bytesize? is false' do
275
+ before do
276
+ LittleWeasel.configure { |config| config.max_invalid_words_bytesize = 0 }
277
+ end
278
+
279
+ it 'does NOT add the word to the cache' do
280
+ expect do
281
+ subject.word_results('IWillBeCached01')
282
+ subject.word_results('IWillBeCached02')
283
+ subject.word_results('IWontBeCached01')
284
+ subject.word_results('IWontBeCached02')
285
+ end.to change { subject.count_all_words }.by(0)
286
+ end
287
+ end
288
+ end
289
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Filters::EnUs::CurrencyFilter do
6
+ subject { described_class.new }
7
+
8
+ #filter_match?
9
+ describe 'filter_match?' do
10
+ context 'when word is currency' do
11
+ it 'returns true' do
12
+ expect(subject.filter_match?('-$1.00')).to eq true
13
+ expect(subject.filter_match?('-$1')).to eq true
14
+ expect(subject.filter_match?('$0')).to eq true
15
+ expect(subject.filter_match?('$1')).to eq true
16
+ expect(subject.filter_match?('$100')).to eq true
17
+ expect(subject.filter_match?('$100.10')).to eq true
18
+ expect(subject.filter_match?('$123456')).to eq true
19
+ expect(subject.filter_match?('+$110.09')).to eq true
20
+ expect(subject.filter_match?('-$1,000.09')).to eq true
21
+ expect(subject.filter_match?('$1000000.00')).to eq true
22
+ expect(subject.filter_match?('$1100000.10')).to eq true
23
+ expect(subject.filter_match?('$120000.01')).to eq true
24
+ expect(subject.filter_match?('$1,000,000.01')).to eq true
25
+ end
26
+ end
27
+
28
+ context 'when word has decimals, but not 2 decimal places' do
29
+ it 'returns false' do
30
+ expect(subject.filter_match?('-$1.1')).to eq false
31
+ expect(subject.filter_match?('$0.1')).to eq false
32
+ expect(subject.filter_match?('$100.9')).to eq false
33
+ expect(subject.filter_match?('+$100.2')).to eq false
34
+ expect(subject.filter_match?('$1000000.0')).to eq false
35
+ expect(subject.filter_match?('$1000000.1')).to eq false
36
+ expect(subject.filter_match?('$1000000.5')).to eq false
37
+ end
38
+ end
39
+
40
+ context 'when word is NOT currency' do
41
+ it 'returns false' do
42
+ expect(subject.filter_match? 'a').to eq false
43
+ expect(subject.filter_match? :a).to eq false
44
+ expect(subject.filter_match? Object.new).to eq false
45
+ end
46
+ end
47
+
48
+ let(:word) { 1 }
49
+
50
+ context 'when #filter_match? returns true' do
51
+ before { allow(subject.class).to receive(:filter_match?).and_return(true) }
52
+
53
+ context 'when #filter_on? is true' do
54
+ it_behaves_like 'the filter matches and #filter_on? is true'
55
+ end
56
+
57
+ context 'when #filter_on? is false' do
58
+ before do
59
+ subject.filter_on = false
60
+ end
61
+
62
+ it_behaves_like 'the filter matches and #filter_on? is false'
63
+ end
64
+ end
65
+
66
+ context 'when #filter_match? returns false' do
67
+ before { allow(subject.class).to receive(:filter_match?).and_return(false) }
68
+
69
+ context 'when #filter_on? is true' do
70
+ it_behaves_like 'the filter DOES NOT match and #filter_on? is true'
71
+ end
72
+
73
+ context 'when #filter_on? is false' do
74
+ let(:filter_on) { false }
75
+
76
+ it_behaves_like 'the filter DOES NOT match and #filter_on? is false'
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Filters::EnUs::NumericFilter do
6
+ subject { described_class.new }
7
+
8
+ #filter_match?
9
+ describe 'filter_match?' do
10
+ context 'when word is a number' do
11
+ it 'returns true' do
12
+ expect(subject.filter_match?('-1.00')).to eq true
13
+ expect(subject.filter_match?('-1')).to eq true
14
+ expect(subject.filter_match?('0')).to eq true
15
+ expect(subject.filter_match?('1')).to eq true
16
+ expect(subject.filter_match?('100')).to eq true
17
+ expect(subject.filter_match?('100.10')).to eq true
18
+ expect(subject.filter_match?(1234_56)).to eq true
19
+ expect(subject.filter_match?('+100.0')).to eq true
20
+ expect(subject.filter_match?(1_000_000.00)).to eq true
21
+ expect(subject.filter_match?(1_000_000.10)).to eq true
22
+ expect(subject.filter_match?(1_000_000.01)).to eq true
23
+ end
24
+ end
25
+
26
+ context 'when word is NOT a number' do
27
+ it 'returns false' do
28
+ expect(subject.filter_match? 'a').to eq false
29
+ expect(subject.filter_match? :a).to eq false
30
+ expect(subject.filter_match? Object.new).to eq false
31
+ end
32
+ end
33
+
34
+ let(:word) { 1 }
35
+
36
+ context 'when #filter_match? returns true' do
37
+ before { allow(subject.class).to receive(:filter_match?).and_return(true) }
38
+
39
+ context 'when #filter_on? is true' do
40
+ it_behaves_like 'the filter matches and #filter_on? is true'
41
+ end
42
+
43
+ context 'when #filter_on? is false' do
44
+ before do
45
+ subject.filter_on = false
46
+ end
47
+
48
+ it_behaves_like 'the filter matches and #filter_on? is false'
49
+ end
50
+ end
51
+
52
+ context 'when #filter_match? returns false' do
53
+ before { allow(subject.class).to receive(:filter_match?).and_return(false) }
54
+
55
+ context 'when #filter_on? is true' do
56
+ it_behaves_like 'the filter DOES NOT match and #filter_on? is true'
57
+ end
58
+
59
+ context 'when #filter_on? is false' do
60
+ let(:filter_on) { false }
61
+
62
+ it_behaves_like 'the filter DOES NOT match and #filter_on? is false'
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Filters::EnUs::SingleCharacterWordFilter do
6
+ subject { described_class.new }
7
+
8
+ #filter_match?
9
+ describe '#filter_match?' do
10
+ context 'when word single character word' do
11
+ it 'returns true' do
12
+ %w(a A I).each do |number|
13
+ expect(subject.filter_match? number).to eq true
14
+ end
15
+ end
16
+ end
17
+
18
+ context 'when word is NOT a single character word' do
19
+ it 'returns false' do
20
+ expect(subject.filter_match? 'X').to eq false
21
+ expect(subject.filter_match? :a).to eq false
22
+ expect(subject.filter_match? Object.new).to eq false
23
+ end
24
+ end
25
+
26
+ let(:word) { 'x' }
27
+
28
+ context 'when #filter_match? returns true' do
29
+ before { allow(subject.class).to receive(:filter_match?).and_return(true) }
30
+
31
+ context 'when #filter_on? is true' do
32
+ it_behaves_like 'the filter matches and #filter_on? is true'
33
+ end
34
+
35
+ context 'when #filter_on? is false' do
36
+ before do
37
+ subject.filter_on = false
38
+ end
39
+
40
+ it_behaves_like 'the filter matches and #filter_on? is false'
41
+ end
42
+ end
43
+
44
+ context 'when #filter_match? returns false' do
45
+ before { allow(subject.class).to receive(:filter_match?).and_return(false) }
46
+
47
+ context 'when #filter_on? is true' do
48
+ it_behaves_like 'the filter DOES NOT match and #filter_on? is true'
49
+ end
50
+
51
+ context 'when #filter_on? is false' do
52
+ let(:filter_on) { false }
53
+
54
+ it_behaves_like 'the filter DOES NOT match and #filter_on? is false'
55
+ end
56
+ end
57
+ end
58
+ end