LittleWeasel 3.0.4 → 5.0.1

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 (153) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/codeql-analysis.yml +72 -0
  3. data/.gitignore +19 -17
  4. data/.reek.yml +17 -0
  5. data/.rspec +4 -2
  6. data/.rubocop.yml +187 -0
  7. data/.ruby-version +1 -1
  8. data/.yardopts +2 -0
  9. data/CHANGELOG.md +21 -1
  10. data/Gemfile +3 -1
  11. data/Gemfile.lock +114 -0
  12. data/Jenkinsfile +20 -0
  13. data/LittleWeasel.gemspec +31 -18
  14. data/README.md +408 -42
  15. data/Rakefile +296 -3
  16. data/lib/LittleWeasel/block_results.rb +81 -0
  17. data/lib/LittleWeasel/configure.rb +98 -0
  18. data/lib/LittleWeasel/dictionary.rb +125 -0
  19. data/lib/LittleWeasel/dictionary_key.rb +48 -0
  20. data/lib/LittleWeasel/dictionary_manager.rb +91 -0
  21. data/lib/LittleWeasel/errors/dictionary_file_already_loaded_error.rb +9 -0
  22. data/lib/LittleWeasel/errors/dictionary_file_empty_error.rb +8 -0
  23. data/lib/LittleWeasel/errors/dictionary_file_not_found_error.rb +8 -0
  24. data/lib/LittleWeasel/errors/dictionary_file_too_large_error.rb +16 -0
  25. data/lib/LittleWeasel/errors/language_required_error.rb +8 -0
  26. data/lib/LittleWeasel/errors/must_override_error.rb +8 -0
  27. data/lib/LittleWeasel/filters/en_us/currency_filter.rb +19 -0
  28. data/lib/LittleWeasel/filters/en_us/numeric_filter.rb +19 -0
  29. data/lib/LittleWeasel/filters/en_us/single_character_word_filter.rb +21 -0
  30. data/lib/LittleWeasel/filters/word_filter.rb +59 -0
  31. data/lib/LittleWeasel/filters/word_filter_managable.rb +80 -0
  32. data/lib/LittleWeasel/filters/word_filter_validatable.rb +31 -0
  33. data/lib/LittleWeasel/filters/word_filterable.rb +19 -0
  34. data/lib/LittleWeasel/filters/word_filters_validatable.rb +29 -0
  35. data/lib/LittleWeasel/metadata/dictionary_metadata.rb +145 -0
  36. data/lib/LittleWeasel/metadata/invalid_words_metadata.rb +134 -0
  37. data/lib/LittleWeasel/metadata/invalid_words_service_results.rb +45 -0
  38. data/lib/LittleWeasel/metadata/metadata_observable_validatable.rb +22 -0
  39. data/lib/LittleWeasel/metadata/metadata_observerable.rb +90 -0
  40. data/lib/LittleWeasel/metadata/metadatable.rb +134 -0
  41. data/lib/LittleWeasel/modules/class_name_to_symbol.rb +26 -0
  42. data/lib/LittleWeasel/modules/configurable.rb +26 -0
  43. data/lib/LittleWeasel/modules/deep_dup.rb +11 -0
  44. data/lib/LittleWeasel/modules/dictionary_cache_keys.rb +34 -0
  45. data/lib/LittleWeasel/modules/dictionary_cache_servicable.rb +26 -0
  46. data/lib/LittleWeasel/modules/dictionary_cache_validatable.rb +18 -0
  47. data/lib/LittleWeasel/modules/dictionary_creator_servicable.rb +27 -0
  48. data/lib/LittleWeasel/modules/dictionary_file_loader.rb +67 -0
  49. data/lib/LittleWeasel/modules/dictionary_key_validatable.rb +17 -0
  50. data/lib/LittleWeasel/modules/dictionary_keyable.rb +24 -0
  51. data/lib/LittleWeasel/modules/dictionary_metadata_servicable.rb +29 -0
  52. data/lib/LittleWeasel/modules/dictionary_metadata_validatable.rb +15 -0
  53. data/lib/LittleWeasel/modules/dictionary_source_validatable.rb +15 -0
  54. data/lib/LittleWeasel/modules/dictionary_sourceable.rb +86 -0
  55. data/lib/LittleWeasel/modules/dictionary_validatable.rb +18 -0
  56. data/lib/LittleWeasel/modules/language.rb +24 -0
  57. data/lib/LittleWeasel/modules/language_validatable.rb +14 -0
  58. data/lib/LittleWeasel/modules/locale.rb +23 -0
  59. data/lib/LittleWeasel/modules/order_validatable.rb +16 -0
  60. data/lib/LittleWeasel/modules/orderable.rb +17 -0
  61. data/lib/LittleWeasel/modules/region.rb +24 -0
  62. data/lib/LittleWeasel/modules/region_validatable.rb +14 -0
  63. data/lib/LittleWeasel/modules/tag_validatable.rb +14 -0
  64. data/lib/LittleWeasel/modules/taggable.rb +31 -0
  65. data/lib/LittleWeasel/modules/word_results_validatable.rb +28 -0
  66. data/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor.rb +22 -0
  67. data/lib/LittleWeasel/preprocessors/preprocessed_word.rb +29 -0
  68. data/lib/LittleWeasel/preprocessors/preprocessed_word_validatable.rb +56 -0
  69. data/lib/LittleWeasel/preprocessors/preprocessed_words.rb +59 -0
  70. data/lib/LittleWeasel/preprocessors/preprocessed_words_validatable.rb +28 -0
  71. data/lib/LittleWeasel/preprocessors/word_preprocessable.rb +19 -0
  72. data/lib/LittleWeasel/preprocessors/word_preprocessor.rb +123 -0
  73. data/lib/LittleWeasel/preprocessors/word_preprocessor_managable.rb +114 -0
  74. data/lib/LittleWeasel/preprocessors/word_preprocessor_validatable.rb +40 -0
  75. data/lib/LittleWeasel/preprocessors/word_preprocessors_validatable.rb +24 -0
  76. data/lib/LittleWeasel/services/dictionary_cache_service.rb +211 -0
  77. data/lib/LittleWeasel/services/dictionary_creator_service.rb +94 -0
  78. data/lib/LittleWeasel/services/dictionary_file_loader_service.rb +37 -0
  79. data/lib/LittleWeasel/services/dictionary_killer_service.rb +35 -0
  80. data/lib/LittleWeasel/services/dictionary_metadata_service.rb +116 -0
  81. data/lib/LittleWeasel/services/invalid_words_service.rb +59 -0
  82. data/lib/LittleWeasel/version.rb +3 -1
  83. data/lib/LittleWeasel/word_results.rb +146 -0
  84. data/lib/LittleWeasel.rb +72 -186
  85. data/spec/factories/dictionary.rb +43 -0
  86. data/spec/factories/dictionary_cache_service.rb +95 -0
  87. data/spec/factories/dictionary_creator_service.rb +16 -0
  88. data/spec/factories/dictionary_file_loader_service.rb +13 -0
  89. data/spec/factories/dictionary_hash.rb +39 -0
  90. data/spec/factories/dictionary_key.rb +14 -0
  91. data/spec/factories/dictionary_killer_service.rb +14 -0
  92. data/spec/factories/dictionary_manager.rb +10 -0
  93. data/spec/factories/dictionary_metadata.rb +16 -0
  94. data/spec/factories/dictionary_metadata_service.rb +16 -0
  95. data/spec/factories/numeric_filter.rb +12 -0
  96. data/spec/factories/preprocessed_word.rb +16 -0
  97. data/spec/factories/preprocessed_words.rb +41 -0
  98. data/spec/factories/single_character_word_filter.rb +12 -0
  99. data/spec/factories/word_results.rb +16 -0
  100. data/spec/lib/LittleWeasel/block_results_spec.rb +248 -0
  101. data/spec/lib/LittleWeasel/configure_spec.rb +74 -0
  102. data/spec/lib/LittleWeasel/dictionary_key_spec.rb +118 -0
  103. data/spec/lib/LittleWeasel/dictionary_manager_spec.rb +166 -0
  104. data/spec/lib/LittleWeasel/dictionary_spec.rb +289 -0
  105. data/spec/lib/LittleWeasel/filters/en_us/currency_filter_spec.rb +80 -0
  106. data/spec/lib/LittleWeasel/filters/en_us/numeric_filter_spec.rb +66 -0
  107. data/spec/lib/LittleWeasel/filters/en_us/single_character_word_filter_spec.rb +58 -0
  108. data/spec/lib/LittleWeasel/filters/word_filter_managable_spec.rb +180 -0
  109. data/spec/lib/LittleWeasel/filters/word_filter_spec.rb +151 -0
  110. data/spec/lib/LittleWeasel/filters/word_filter_validatable_spec.rb +94 -0
  111. data/spec/lib/LittleWeasel/filters/word_filters_validatable_spec.rb +48 -0
  112. data/spec/lib/LittleWeasel/integraton_tests/dictionary_integration_spec.rb +201 -0
  113. data/spec/lib/LittleWeasel/metadata/dictionary_creator_servicable_spec.rb +54 -0
  114. data/spec/lib/LittleWeasel/metadata/dictionary_metadata_spec.rb +209 -0
  115. data/spec/lib/LittleWeasel/metadata/invalid_words_metadata_spec.rb +155 -0
  116. data/spec/lib/LittleWeasel/metadata/metadata_observerable_spec.rb +31 -0
  117. data/spec/lib/LittleWeasel/metadata/metadatable_spec.rb +35 -0
  118. data/spec/lib/LittleWeasel/modules/class_name_to_symbol_spec.rb +21 -0
  119. data/spec/lib/LittleWeasel/modules/dictionary_file_loader_spec.rb +125 -0
  120. data/spec/lib/LittleWeasel/modules/dictionary_sourceable_spec.rb +81 -0
  121. data/spec/lib/LittleWeasel/modules/language_spec.rb +112 -0
  122. data/spec/lib/LittleWeasel/modules/locale_spec.rb +95 -0
  123. data/spec/lib/LittleWeasel/modules/region_spec.rb +112 -0
  124. data/spec/lib/LittleWeasel/preprocessors/en_us/capitalize_preprocessor_spec.rb +34 -0
  125. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_spec.rb +105 -0
  126. data/spec/lib/LittleWeasel/preprocessors/preprocessed_word_validatable_spec.rb +143 -0
  127. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_spec.rb +77 -0
  128. data/spec/lib/LittleWeasel/preprocessors/preprocessed_words_validatable_spec.rb +58 -0
  129. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_managable_spec.rb +242 -0
  130. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_spec.rb +218 -0
  131. data/spec/lib/LittleWeasel/preprocessors/word_preprocessor_validatable_spec.rb +109 -0
  132. data/spec/lib/LittleWeasel/preprocessors/word_preprocessors_validatable_spec.rb +49 -0
  133. data/spec/lib/LittleWeasel/services/dictionary_cache_service_spec.rb +444 -0
  134. data/spec/lib/LittleWeasel/services/dictionary_creator_service_spec.rb +119 -0
  135. data/spec/lib/LittleWeasel/services/dictionary_file_loader_service_spec.rb +71 -0
  136. data/spec/lib/LittleWeasel/services/dictionary_metadata_service_spec.rb +279 -0
  137. data/spec/lib/LittleWeasel/word_results_spec.rb +275 -0
  138. data/spec/lib/LittleWeasel/workflow/workflow_spec.rb +20 -0
  139. data/spec/spec_helper.rb +117 -6
  140. data/spec/support/factory_bot.rb +15 -0
  141. data/spec/support/file_helpers.rb +46 -0
  142. data/spec/support/files/empty-dictionary.txt +0 -0
  143. data/{lib/dictionary → spec/support/files/en-US-big.txt} +262156 -31488
  144. data/spec/support/files/en-US-tagged.txt +26 -0
  145. data/spec/support/files/en-US.txt +26 -0
  146. data/spec/support/files/en.txt +26 -0
  147. data/spec/support/files/es-ES.txt +27 -0
  148. data/spec/support/files/es.txt +27 -0
  149. data/spec/support/general_helpers.rb +68 -0
  150. data/spec/support/shared_contexts.rb +107 -0
  151. data/spec/support/shared_examples.rb +105 -0
  152. metadata +418 -70
  153. data/spec/checker/checker_spec.rb +0 -286
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Modules::ClassNameToSymbol, type: :module do
6
+ ClassNameToSymbol = described_class
7
+
8
+ subject do
9
+ module TestModule
10
+ class TestMeUp
11
+ include ClassNameToSymbol
12
+ end
13
+ end
14
+ end
15
+
16
+ describe '#to_sym' do
17
+ it 'returns the class name as a snake-case Symbol with namespaces removed' do
18
+ expect(subject.new.to_sym).to eq :test_me_up
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Modules::DictionaryFileLoader, type: :module do
6
+ subject do
7
+ dictionary_cache_service.init dictionary_cache: dictionary_cache
8
+ dictionary_file_loader
9
+ end
10
+
11
+ let(:dictionary_file_loader) do
12
+ Class.new do
13
+ include LittleWeasel::Modules::DictionaryFileLoader
14
+
15
+ attr_reader :dictionary_key, :dictionary_cache, :config
16
+
17
+ def initialize(dictionary_key, dictionary_cache)
18
+ self.dictionary_key = dictionary_key
19
+ self.dictionary_cache = dictionary_cache
20
+ self.config = LittleWeasel.configuration
21
+ end
22
+
23
+ private
24
+
25
+ attr_writer :dictionary_key, :dictionary_cache, :config
26
+ end.new(dictionary_key, dictionary_cache)
27
+ end
28
+
29
+ let(:language) { :en }
30
+ let(:region) { :us }
31
+ let(:tag) {}
32
+
33
+ let(:dictionary_cache_service) { LittleWeasel::Services::DictionaryCacheService }
34
+ let(:dictionary_key) { LittleWeasel::DictionaryKey.new(language: language, region: region, tag: tag) }
35
+ let(:key) { dictionary_key.key }
36
+ let(:file) { dictionary_path_for locale: dictionary_key.locale }
37
+ let(:dictionary_file_key) { file }
38
+ let(:dictionary_cache) { {} }
39
+
40
+ #load
41
+ describe '#load' do
42
+ context 'with an invalid dictionary file' do
43
+ context 'when it cannot be found' do
44
+ let(:dictionary_path) { region_dictionary_path language: :bad, region: :worse }
45
+
46
+ it 'raises an error' do
47
+ expect { subject.load dictionary_path }.to raise_error LittleWeasel::Errors::DictionaryFileNotFoundError
48
+ end
49
+ end
50
+
51
+ context 'when it is empty' do
52
+ let(:dictionary_path) { dictionary_path_for file_name: 'empty-dictionary' }
53
+
54
+ it 'raises an error' do
55
+ expect { subject.load dictionary_path }.to raise_error LittleWeasel::Errors::DictionaryFileEmptyError
56
+ end
57
+ end
58
+
59
+ context 'when it is too large' do
60
+ before do
61
+ allow(LittleWeasel.configuration).to receive(:max_dictionary_file_bytes).and_return 1
62
+ end
63
+
64
+ let(:dictionary_path) { language_dictionary_path language: :en }
65
+
66
+ it 'raises an error' do
67
+ expect { subject.load dictionary_path }.to raise_error LittleWeasel::Errors::DictionaryFileTooLargeError
68
+ end
69
+ end
70
+ end
71
+
72
+ context 'with a valid dictionary file' do
73
+ subject { dictionary_file_loader.load dictionary_path }
74
+
75
+ let(:dictionary_path) { region_dictionary_path language: language, region: region }
76
+
77
+ context 'when the dictionary file is already loaded/cached' do
78
+ before { subject }
79
+
80
+ it 'does not raise an error' do
81
+ expect { subject }.to_not raise_error
82
+ end
83
+ end
84
+
85
+ context 'when the dictionary is NOT already loaded/cached' do
86
+ let(:expected_dictionary_key_key) { LittleWeasel::DictionaryKey.new(language: language, region: region, tag: tag).key }
87
+ let(:expected_results) do
88
+ ['apple',
89
+ 'better',
90
+ 'cat',
91
+ 'dog',
92
+ 'everyone',
93
+ 'fat',
94
+ 'game',
95
+ 'help',
96
+ 'italic',
97
+ 'jasmine',
98
+ 'kelp',
99
+ 'love',
100
+ 'man',
101
+ 'nope',
102
+ 'octopus',
103
+ 'popeye',
104
+ 'queue',
105
+ 'ruby',
106
+ 'stop',
107
+ 'top',
108
+ 'ultimate',
109
+ 'very',
110
+ 'was',
111
+ 'xylophone',
112
+ 'yes',
113
+ 'zebra']
114
+ end
115
+
116
+ it 'returns an Array of dictionary words loaded from the file' do
117
+ # This test won't pass if we're not testing against an assumed
118
+ # dictionary file.
119
+ expect(dictionary_key.key).to eq expected_dictionary_key_key
120
+ expect(subject).to eq expected_results
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Modules::DictionarySourceable, type: :module do
6
+ subject { MockDictionarySourceable.new(dictionary_memory_source) }
7
+
8
+ DictionarySourceable = described_class
9
+
10
+ class MockDictionarySourceable
11
+ include DictionarySourceable
12
+
13
+ def initialize(dictionary_source)
14
+ self.dictionary_source = dictionary_source
15
+ end
16
+ end
17
+
18
+ let(:dictionary_memory_source) { described_class.memory_source }
19
+ let(:dictionary_file_source) { language_dictionary_path language: :en }
20
+
21
+ #.MEMORY_SOURCE
22
+ describe '::MEMORY_SOURCE' do
23
+ it 'returns the memory source prefix' do
24
+ expect(described_class::MEMORY_SOURCE).to eq '*'
25
+ end
26
+ end
27
+
28
+ #.memory_source
29
+ describe '.memory_source' do
30
+ it 'returns a new memory source' do
31
+ expect(described_class.memory_source).to be_truthy
32
+ end
33
+ end
34
+
35
+ #.file_source?
36
+ describe '.file_source?' do
37
+ context 'when dictionary_source is a file source' do
38
+ it 'returns truthy' do
39
+ expect(described_class.file_source? dictionary_file_source).to be_truthy
40
+ end
41
+ end
42
+
43
+ context 'when dictionary_source is NOT a file source' do
44
+ it 'returns falsey' do
45
+ expect(described_class.file_source? dictionary_memory_source).to be_falsey
46
+ end
47
+ end
48
+ end
49
+
50
+ #.memory_source?
51
+ describe '.memory_source?' do
52
+ context 'when dictionary_source is a memory source' do
53
+ it 'returns truthy if argument is a valid memory source' do
54
+ expect(described_class.memory_source? '*12345678').to be_truthy
55
+ expect(described_class.memory_source? '*abcdef00').to be_truthy
56
+ expect(described_class.memory_source? '*ABCDEF00').to be_truthy
57
+ expect(described_class.memory_source? '*aBcDeF00').to be_truthy
58
+ end
59
+
60
+ it 'returns falsey if argument is NOT a memory source' do
61
+ expect(described_class.memory_source? '*123456789').to be_falsey
62
+ expect(described_class.memory_source? '*abcdefg0').to be_falsey
63
+ expect(described_class.memory_source? '*ABCDEFG0').to be_falsey
64
+ expect(described_class.memory_source? '*aBcDeFg0').to be_falsey
65
+ expect(described_class.memory_source? '$12345678').to be_falsey
66
+
67
+ expect(described_class.memory_source? '123456789').to be_falsey
68
+ expect(described_class.memory_source? 'abcdefg0').to be_falsey
69
+ expect(described_class.memory_source? 'ABCDEFG0').to be_falsey
70
+ expect(described_class.memory_source? 'aBcDeFg0').to be_falsey
71
+ expect(described_class.memory_source? '123456789').to be_falsey
72
+ end
73
+ end
74
+
75
+ context 'when dictionary_source is a file source' do
76
+ it 'returns falsey' do
77
+ expect(described_class.memory_source? dictionary_file_source).to be_falsey
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Modules::Language, type: :module do
6
+ Language = described_class
7
+
8
+ subject do
9
+ Class.new do
10
+ include Language
11
+
12
+ attr_reader :language
13
+
14
+ def initialize(language)
15
+ self.language = language
16
+ end
17
+
18
+ private
19
+
20
+ attr_writer :language
21
+ end.new(language)
22
+ end
23
+
24
+ let(:language) {}
25
+
26
+ #language?
27
+ describe '#language?' do
28
+ context 'when language is present?' do
29
+ let(:language) { :es }
30
+
31
+ it 'returns true' do
32
+ expect(subject.language?).to eq true
33
+ end
34
+ end
35
+
36
+ context 'when language is NOT present?' do
37
+ it 'returns false' do
38
+ expect(subject.language?).to eq false
39
+ end
40
+ end
41
+ end
42
+
43
+ #normalize_language!
44
+ describe '#normalize_language!' do
45
+ context 'when language is present?' do
46
+ context 'when language responds to #upcase!' do
47
+ before do
48
+ subject.normalize_language!
49
+ end
50
+
51
+ let(:language) { :AA }
52
+
53
+ it 'changes language to lower case' do
54
+ expect(subject.language).to eq :aa
55
+ end
56
+ end
57
+
58
+ context 'when language DOES NOT respond to #downcase' do
59
+ let(:language) { Object.new }
60
+
61
+ it 'raises an error' do
62
+ expect { subject.normalize_language! }.to raise_error(NoMethodError, /undefined method `downcase'/)
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'when language is NOT present?' do
68
+ before do
69
+ subject.normalize_language!
70
+ end
71
+
72
+ it 'does nothing' do
73
+ expect(subject.language).to be_nil
74
+ end
75
+ end
76
+ end
77
+
78
+ #.normalize_language
79
+ describe '#.normalize_language' do
80
+ context 'with a non-nil language' do
81
+ context 'when passing a Symbol' do
82
+ let(:language) { :AbCdEfG }
83
+
84
+ it 'converts the language to a lower-case Symbol' do
85
+ expect(described_class.normalize_language(language)).to eq :abcdefg
86
+ end
87
+ end
88
+
89
+ context 'when passing a String' do
90
+ let(:language) { 'AbCdEfG' }
91
+
92
+ it 'converts the language to a lower-case String' do
93
+ expect(described_class.normalize_language(language)).to eq 'abcdefg'
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'with a nil language' do
99
+ it 'returns nil' do
100
+ expect(described_class.normalize_language(language)).to be_nil
101
+ end
102
+ end
103
+
104
+ context 'when language does not respond to #downcase' do
105
+ let(:language) { 1 }
106
+
107
+ it 'returns nil' do
108
+ expect { described_class.normalize_language(language) }.to raise_error(NoMethodError, /undefined method `downcase'/)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Modules::Locale, type: :module do
6
+ Locale = described_class
7
+
8
+ subject do
9
+ Class.new do
10
+ include Locale
11
+
12
+ attr_reader :language, :region
13
+
14
+ def initialize(language, region)
15
+ self.language = language
16
+ self.region = region
17
+ end
18
+
19
+ private
20
+
21
+ attr_writer :language, :region
22
+ end.new(language, region)
23
+ end
24
+
25
+ let(:language) {}
26
+ let(:region) {}
27
+
28
+ #locale
29
+ describe '#locale' do
30
+ context 'with valid arguments' do
31
+ context 'with valid language' do
32
+ let(:language) { :en }
33
+
34
+ it 'returns the expected locale (language only)' do
35
+ expect(subject.locale).to eq 'en'
36
+ end
37
+ end
38
+
39
+ context 'with valid language and region' do
40
+ let(:language) { :en }
41
+ let(:region) { :us }
42
+
43
+ it 'returns the expected locale (language and region)' do
44
+ expect(subject.locale).to eq 'en-US'
45
+ end
46
+
47
+ describe 'normalizes language and region to the proper case' do
48
+ let(:language) { :EN }
49
+ let(:region) { :us }
50
+
51
+ it 'returns the expected locale with language lowercase and region uppercase' do
52
+ expect(subject.locale).to eq 'en-US'
53
+ end
54
+ end
55
+ end
56
+
57
+ context 'with valid language and nil region' do
58
+ let(:language) { :en }
59
+ let(:region) {}
60
+
61
+ it 'returns the expected locale (language only)' do
62
+ expect(subject.locale).to eq 'en'
63
+ end
64
+ end
65
+
66
+ context 'with valid language and blank region' do
67
+ let(:language) { :en }
68
+ let(:region) { '' }
69
+
70
+ it 'returns the expected locale (language only)' do
71
+ expect(subject.locale).to eq 'en'
72
+ end
73
+ end
74
+ end
75
+
76
+ context 'with invalid arguments' do
77
+ context 'when argument language does not respond to #downcase' do
78
+ let(:language) { 1 }
79
+
80
+ it 'raises an error' do
81
+ expect { subject.locale }.to raise_error(NoMethodError, /undefined method `downcase'/)
82
+ end
83
+ end
84
+
85
+ context 'when argument region does not respond to #upcase' do
86
+ let(:language) { :en }
87
+ let(:region) { 1 }
88
+
89
+ it 'raises an error' do
90
+ expect { subject.locale }.to raise_error(NoMethodError, /undefined method `upcase'/)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Modules::Region, type: :module do
6
+ Region = described_class
7
+
8
+ subject do
9
+ Class.new do
10
+ include Region
11
+
12
+ attr_reader :region
13
+
14
+ def initialize(region)
15
+ self.region = region
16
+ end
17
+
18
+ private
19
+
20
+ attr_writer :region
21
+ end.new(region)
22
+ end
23
+
24
+ let(:region) {}
25
+
26
+ #region?
27
+ describe '#region?' do
28
+ context 'when region is present?' do
29
+ let(:region) { :es }
30
+
31
+ it 'returns true' do
32
+ expect(subject.region?).to eq true
33
+ end
34
+ end
35
+
36
+ context 'when region is NOT present?' do
37
+ it 'returns false' do
38
+ expect(subject.region?).to eq false
39
+ end
40
+ end
41
+ end
42
+
43
+ #normalize_region!
44
+ describe '#normalize_region!' do
45
+ context 'when region is present?' do
46
+ context 'when region responds to #upcase' do
47
+ before do
48
+ subject.normalize_region!
49
+ end
50
+
51
+ let(:region) { :aa }
52
+
53
+ it 'changes region to upper case' do
54
+ expect(subject.region).to eq :AA
55
+ end
56
+ end
57
+
58
+ context 'when region DOES NOT respond to #upcase' do
59
+ let(:region) { Object.new }
60
+
61
+ it 'raises an error' do
62
+ expect { subject.normalize_region! }.to raise_error(NoMethodError, /undefined method `upcase'/)
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'when region is NOT present?' do
68
+ before do
69
+ subject.normalize_region!
70
+ end
71
+
72
+ it 'does nothing' do
73
+ expect(subject.region).to be_nil
74
+ end
75
+ end
76
+ end
77
+
78
+ #.normalize_region
79
+ describe '#.normalize_region' do
80
+ context 'with a non-nil region' do
81
+ context 'when passing a Symbol' do
82
+ let(:region) { :AbCdEfG }
83
+
84
+ it 'converts the region to a upper-case Symbol' do
85
+ expect(described_class.normalize_region(region)).to eq :ABCDEFG
86
+ end
87
+ end
88
+
89
+ context 'when passing a String' do
90
+ let(:region) { 'AbCdEfG' }
91
+
92
+ it 'converts the region to a upper-case String' do
93
+ expect(described_class.normalize_region(region)).to eq 'ABCDEFG'
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'with a nil region' do
99
+ it 'returns nil' do
100
+ expect(described_class.normalize_region(region)).to be_nil
101
+ end
102
+ end
103
+
104
+ context 'when region does not respond to #upcase' do
105
+ let(:region) { 1 }
106
+
107
+ it 'returns nil' do
108
+ expect { described_class.normalize_region(region) }.to raise_error(NoMethodError, /undefined method `upcase'/)
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literals: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::EnUs::CapitalizePreprocessor do
6
+ subject { described_class.new }
7
+
8
+ #.new
9
+ describe '.new' do
10
+ it 'instantiates the object' do
11
+ expect { subject }.to_not raise_error
12
+ end
13
+
14
+ describe '#order' do
15
+ it 'sets #order to 0 by default' do
16
+ expect(subject.order).to eq 0
17
+ end
18
+ end
19
+
20
+ describe '#preprocessor_on' do
21
+ it 'sets #preprocessor_on to true by default' do
22
+ expect(subject.preprocessor_on).to eq true
23
+ end
24
+ end
25
+ end
26
+
27
+ #.preprocess
28
+ describe '.preprocess' do
29
+ it 'processes and capitalizes the word' do
30
+ expect(described_class.preprocess 'wOrD').to eq [true, 'Word']
31
+ expect(described_class.preprocess 'Word').to eq [true, 'Word']
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe LittleWeasel::Preprocessors::PreprocessedWord do
6
+ subject do
7
+ described_class.new(
8
+ original_word: original_word,
9
+ preprocessed_word: preprocessed_word,
10
+ preprocessor: preprocessor,
11
+ preprocessed: preprocessed,
12
+ preprocessor_order: preprocessor_order
13
+ )
14
+ end
15
+
16
+ let(:original_word) { :original_word }
17
+ let(:preprocessed_word) { :preprocessed_word }
18
+ let(:preprocessor) { :preprocessor }
19
+ let(:preprocessed) { true }
20
+ let(:preprocessor_order) { :preprocessor_order }
21
+
22
+ #.new
23
+ describe '.new' do
24
+ context 'initializes the attributes' do
25
+ describe '#original_word' do
26
+ it 'is initialized' do
27
+ expect(subject.original_word).to eq :original_word
28
+ end
29
+ end
30
+
31
+ describe '#preprocessed_word' do
32
+ it 'is initialized' do
33
+ expect(subject.preprocessed_word).to eq :preprocessed_word
34
+ end
35
+ end
36
+
37
+ describe '#preprocessor' do
38
+ it 'is initialized' do
39
+ expect(subject.preprocessor).to eq :preprocessor
40
+ end
41
+ end
42
+
43
+ describe '#preprocessor_order' do
44
+ it 'is initialized' do
45
+ expect(subject.preprocessor_order).to eq :preprocessor_order
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ # attributes
52
+ context 'attributes' do
53
+ describe 'original_word=' do
54
+ let(:changed_to) { :original_word_changed }
55
+
56
+ it 'sets the attribute' do
57
+ subject.original_word = changed_to
58
+ expect(subject.original_word).to eq changed_to
59
+ end
60
+ end
61
+
62
+ describe 'preprocessed_word=' do
63
+ let(:changed_to) { :preprocessed_word_changed }
64
+
65
+ it 'sets the attribute' do
66
+ subject.preprocessed_word = changed_to
67
+ expect(subject.preprocessed_word).to eq changed_to
68
+ end
69
+ end
70
+
71
+ describe 'preprocessor=' do
72
+ let(:changed_to) { :preprocessor_changed }
73
+
74
+ it 'sets the attribute' do
75
+ subject.preprocessor = changed_to
76
+ expect(subject.preprocessor).to eq changed_to
77
+ end
78
+ end
79
+
80
+ describe 'preprocessor_order=' do
81
+ let(:changed_to) { :preprocessor_order_changed }
82
+
83
+ it 'sets the attribute' do
84
+ subject.preprocessor_order = changed_to
85
+ expect(subject.preprocessor_order).to eq changed_to
86
+ end
87
+ end
88
+
89
+ describe '#preprocessed?' do
90
+ context 'when preprocessed is true' do
91
+ it 'returns true' do
92
+ expect(subject.preprocessed?).to eq true
93
+ end
94
+ end
95
+
96
+ context 'when preprocessed is false' do
97
+ let(:preprocessed) { false }
98
+
99
+ it 'returns false' do
100
+ expect(subject.preprocessed?).to eq false
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end