qonfig 0.25.0 → 0.26.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 +4 -4
- data/.gitignore +0 -2
- data/.rubocop.yml +19 -1
- data/.travis.yml +7 -2
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +102 -0
- data/README.md +2 -0
- data/gemfiles/with_external_deps.gemfile.lock +112 -0
- data/gemfiles/without_external_deps.gemfile.lock +102 -0
- data/lib/qonfig.rb +1 -1
- data/lib/qonfig/commands/definition/load_from_env.rb +2 -0
- data/lib/qonfig/commands/definition/load_from_env/value_converter.rb +2 -0
- data/lib/qonfig/imports/direct_key.rb +8 -2
- data/lib/qonfig/imports/mappings.rb +8 -2
- data/lib/qonfig/loaders/basic.rb +2 -0
- data/lib/qonfig/loaders/json.rb +2 -1
- data/lib/qonfig/settings.rb +5 -1
- data/lib/qonfig/settings/key_matcher.rb +1 -1
- data/lib/qonfig/uploaders/base.rb +2 -0
- data/lib/qonfig/uploaders/yaml.rb +2 -0
- data/lib/qonfig/version.rb +1 -1
- data/qonfig.gemspec +4 -6
- data/sig/.keep +0 -0
- data/spec/features/clear_options_spec.rb +92 -0
- data/spec/features/compacted_config_spec.rb +308 -0
- data/spec/features/composition_spec.rb +207 -0
- data/spec/features/config_definition_and_representation_spec.rb +535 -0
- data/spec/features/definition_order_spec.rb +69 -0
- data/spec/features/dig_functionality_spec.rb +47 -0
- data/spec/features/dot_notation_spec.rb +159 -0
- data/spec/features/export_settings_spec.rb +138 -0
- data/spec/features/expose_json_spec.rb +281 -0
- data/spec/features/expose_self/format_option_dynamic_spec.rb +69 -0
- data/spec/features/expose_self/format_option_json_spec.rb +74 -0
- data/spec/features/expose_self/format_option_unsupported_spec.rb +27 -0
- data/spec/features/expose_self/format_option_yaml_spec.rb +77 -0
- data/spec/features/expose_self_spec.rb +97 -0
- data/spec/features/expose_yaml_spec.rb +263 -0
- data/spec/features/freeze_state_spec.rb +122 -0
- data/spec/features/get_config_keys_spec.rb +62 -0
- data/spec/features/get_config_values_spec.rb +41 -0
- data/spec/features/has_a_key_spec.rb +48 -0
- data/spec/features/import_settings_spec.rb +323 -0
- data/spec/features/indifferent_access_spec.rb +57 -0
- data/spec/features/inheritance_spec.rb +110 -0
- data/spec/features/instantiation_without_class_definition_spec.rb +59 -0
- data/spec/features/iteration_over_setting_keys_spec.rb +48 -0
- data/spec/features/load_from_env_spec.rb +240 -0
- data/spec/features/load_from_json_spec.rb +97 -0
- data/spec/features/load_from_self/format_option_json_spec.rb +31 -0
- data/spec/features/load_from_self/format_option_unsupported_spec.rb +27 -0
- data/spec/features/load_from_self/format_option_yaml_spec.rb +49 -0
- data/spec/features/load_from_self/with_erb_instructions_spec.rb +33 -0
- data/spec/features/load_from_self/with_hash_like_data_representation_spec.rb +66 -0
- data/spec/features/load_from_self/with_non_hash_like_data_representation_spec.rb +19 -0
- data/spec/features/load_from_self/without_end_data_spec.rb +11 -0
- data/spec/features/load_from_yaml_spec.rb +110 -0
- data/spec/features/load_setting_values_from_file/by_instance_method_examples.rb +171 -0
- data/spec/features/load_setting_values_from_file/by_macros_examples.rb +165 -0
- data/spec/features/load_setting_values_from_file/load_from_json_spec.rb +21 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/end_data_with_env_spec.rb +100 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_end_data_spec.rb +129 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_incorrect_end_data_spec.rb +34 -0
- data/spec/features/load_setting_values_from_file/load_from_self/json_format/without_end_data_spec.rb +65 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/end_data_with_env_spec.rb +94 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_end_data_spec.rb +126 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_incorrect_end_data_spec.rb +32 -0
- data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/without_end_data_spec.rb +65 -0
- data/spec/features/load_setting_values_from_file/load_from_yaml_spec.rb +21 -0
- data/spec/features/load_setting_values_from_file/shared_behavior_spec.rb +33 -0
- data/spec/features/mixin_spec.rb +387 -0
- data/spec/features/non_redefineable_core_methods_spec.rb +29 -0
- data/spec/features/plugins/pretty_print_spec.rb +86 -0
- data/spec/features/plugins/toml/expose_self/format_option_toml_spec.rb +71 -0
- data/spec/features/plugins/toml/expose_toml_spec.rb +221 -0
- data/spec/features/plugins/toml/load_from_self/format_option_toml_spec.rb +27 -0
- data/spec/features/plugins/toml/load_from_toml_spec.rb +109 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_from_toml_spec.rb +27 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/end_data_with_env_spec.rb +95 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_end_data_spec.rb +125 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_incorrect_end_data_spec.rb +34 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/without_end_data_spec.rb +65 -0
- data/spec/features/plugins/toml/load_setting_values_from_file/shared_behavior_spec.rb +34 -0
- data/spec/features/plugins/toml/save_to_toml_spec.rb +149 -0
- data/spec/features/plugins/vault/expose_vault_spec.rb +117 -0
- data/spec/features/plugins/vault/load_from_vault_spec.rb +80 -0
- data/spec/features/plugins_spec.rb +89 -0
- data/spec/features/reload_spec.rb +75 -0
- data/spec/features/run_code_with_temporary_settings_spec.rb +104 -0
- data/spec/features/save_to_file/save_to_json_spec.rb +157 -0
- data/spec/features/save_to_file/save_to_yaml_spec.rb +189 -0
- data/spec/features/settings_as_predicates_spec.rb +47 -0
- data/spec/features/settings_redefinition_spec.rb +30 -0
- data/spec/features/slice_functionality_spec.rb +69 -0
- data/spec/features/subset_functionality_spec.rb +49 -0
- data/spec/features/validation_spec.rb +916 -0
- data/spec/fixtures/array_settings.yml +3 -0
- data/spec/fixtures/expose_json/incompatible_root_structure.json +6 -0
- data/spec/fixtures/expose_json/incompatible_structure.json +4 -0
- data/spec/fixtures/expose_json/project.development.json +7 -0
- data/spec/fixtures/expose_json/project.json +30 -0
- data/spec/fixtures/expose_json/project.production.json +7 -0
- data/spec/fixtures/expose_json/project.staging.json +7 -0
- data/spec/fixtures/expose_json/project.test.json +7 -0
- data/spec/fixtures/expose_yaml/incompatible_structure.yml +2 -0
- data/spec/fixtures/expose_yaml/project.development.yml +4 -0
- data/spec/fixtures/expose_yaml/project.production.yml +4 -0
- data/spec/fixtures/expose_yaml/project.staging.yml +4 -0
- data/spec/fixtures/expose_yaml/project.test.yml +4 -0
- data/spec/fixtures/expose_yaml/project.yml +25 -0
- data/spec/fixtures/json_array_sample.json +14 -0
- data/spec/fixtures/json_object_sample.json +9 -0
- data/spec/fixtures/json_with_empty_object.json +6 -0
- data/spec/fixtures/json_with_erb.json +6 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.development.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.production.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.staging.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.test.toml +4 -0
- data/spec/fixtures/plugins/toml/expose_toml/project.toml +27 -0
- data/spec/fixtures/plugins/toml/mini_file.toml +6 -0
- data/spec/fixtures/plugins/toml/toml_sample_with_all_types.toml +72 -0
- data/spec/fixtures/plugins/toml/values_file/with_env.toml +13 -0
- data/spec/fixtures/plugins/toml/values_file/without_env.toml +6 -0
- data/spec/fixtures/rubocop_settings.yml +12 -0
- data/spec/fixtures/shared_settings_with_aliases.yml +10 -0
- data/spec/fixtures/travis_settings.yml +6 -0
- data/spec/fixtures/values_file/with_env.json +19 -0
- data/spec/fixtures/values_file/with_env.yml +17 -0
- data/spec/fixtures/values_file/without_env.json +8 -0
- data/spec/fixtures/values_file/without_env.yml +5 -0
- data/spec/fixtures/with_empty_hash.yml +4 -0
- data/spec/fixtures/with_erb_instructions.yml +3 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/meta_scopes.rb +20 -0
- data/spec/support/spec_support.rb +42 -0
- metadata +128 -11
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe '(#subset)-functionality' do
|
|
4
|
+
specify '#subset functionality works as expected :)' do
|
|
5
|
+
class SubsetableConfig < Qonfig::DataSet
|
|
6
|
+
setting :db do
|
|
7
|
+
setting :creds do
|
|
8
|
+
setting :user, 'D@iVeR'
|
|
9
|
+
setting :data, test: false
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
setting :adapter, :sidekiq
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
config = SubsetableConfig.new
|
|
17
|
+
|
|
18
|
+
# access to the subset (with indifferent keys type)
|
|
19
|
+
expect(config.subset(:db, ['db', :creds], ['db', 'creds', :user], 'adapter')).to match(
|
|
20
|
+
'db' => { 'creds' => { 'user' => 'D@iVeR', 'data' => { test: false } } }, # :db
|
|
21
|
+
'creds' => { 'user' => 'D@iVeR', 'data' => { test: false } }, # ['db', :creds]
|
|
22
|
+
'user' => 'D@iVeR', # ['db', 'creds', :user]
|
|
23
|
+
'adapter' => :sidekiq # 'adepter'
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# try to use subset with with unexistent keys
|
|
27
|
+
# NOTE: :megazavr key does not exist
|
|
28
|
+
expect { config.subset(%i[db creds megazavr]) }.to raise_error(Qonfig::UnknownSettingError)
|
|
29
|
+
# NOTE: :test key does not exist
|
|
30
|
+
expect { config.subset(:db, :test) }.to raise_error(Qonfig::UnknownSettingError)
|
|
31
|
+
|
|
32
|
+
# you cant use subset operation over setting values - you can do it only over the setting keys!
|
|
33
|
+
expect { config.subset(%i[db creds data test]) }.to raise_error(Qonfig::UnknownSettingError)
|
|
34
|
+
|
|
35
|
+
# subset invokation with empty key list
|
|
36
|
+
# rubocop:disable Lint/RedundantSplatExpansion
|
|
37
|
+
expect(config.subset(*[])).to eq({})
|
|
38
|
+
expect(config.subset).to eq({})
|
|
39
|
+
# rubocop:enable Lint/RedundantSplatExpansion
|
|
40
|
+
|
|
41
|
+
# subset invokation over unexistent option
|
|
42
|
+
expect { config.subset(%i[db creds session]) }.to raise_error(Qonfig::UnknownSettingError)
|
|
43
|
+
expect { config.subset(%i[a b c d]) }.to raise_error(Qonfig::UnknownSettingError)
|
|
44
|
+
|
|
45
|
+
# invokation with incorret subset key attributes
|
|
46
|
+
expect { config.subset([:db, :creds, Object.new]) }.to raise_error(Qonfig::ArgumentError)
|
|
47
|
+
expect { config.subset(:db, 123) }.to raise_error(Qonfig::ArgumentError)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,916 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
describe 'Validation' do
|
|
4
|
+
describe 'DSL' do
|
|
5
|
+
specify 'fails when validation method isnt chosen' do
|
|
6
|
+
expect do
|
|
7
|
+
# NOTE: no validation block, no dataset method
|
|
8
|
+
Class.new(Qonfig::DataSet) { validate }
|
|
9
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
specify 'fails when you try to use both block validation and method validation' do
|
|
13
|
+
expect do
|
|
14
|
+
Class.new(Qonfig::DataSet) do
|
|
15
|
+
validate '*', by: :test do # NOTE: dataset mtehod
|
|
16
|
+
true
|
|
17
|
+
end # NOTE: block
|
|
18
|
+
end
|
|
19
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
specify 'fails when you try to use both predefined validator and any validation method' do
|
|
23
|
+
expect do
|
|
24
|
+
Class.new(Qonfig::DataSet) do
|
|
25
|
+
validate '*', :integer do
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
30
|
+
|
|
31
|
+
expect do
|
|
32
|
+
Class.new(Qonfig::DataSet) do
|
|
33
|
+
validate '*', :integer, by: :check
|
|
34
|
+
end
|
|
35
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
36
|
+
|
|
37
|
+
expect do
|
|
38
|
+
Class.new(Qonfig::DataSet) do
|
|
39
|
+
validate '*', :integer, by: :check do
|
|
40
|
+
true
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
specify 'fails when required predefined validator does not exist' do
|
|
47
|
+
# NOTE: incorrect name => error
|
|
48
|
+
expect do
|
|
49
|
+
Class.new(Qonfig::DataSet) do
|
|
50
|
+
validate '*', 1923923
|
|
51
|
+
end
|
|
52
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
53
|
+
|
|
54
|
+
# NOTE: nonexistent predefined validator => error
|
|
55
|
+
expect do
|
|
56
|
+
Class.new(Qonfig::DataSet) do
|
|
57
|
+
validate '*', :abracadabra
|
|
58
|
+
end
|
|
59
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
60
|
+
|
|
61
|
+
# NOTE: existent predefined validator => ok
|
|
62
|
+
expect do
|
|
63
|
+
Class.new(Qonfig::DataSet) do
|
|
64
|
+
validate '*', :integer
|
|
65
|
+
validate '*', :float
|
|
66
|
+
validate '*', :string
|
|
67
|
+
validate '*', :symbol
|
|
68
|
+
validate '*', :numeric
|
|
69
|
+
validate '*', :hash, strict: true
|
|
70
|
+
validate '*', :array, strict: true
|
|
71
|
+
validate '*', :big_decimal, strict: true
|
|
72
|
+
validate '*', :boolean, strict: true
|
|
73
|
+
end
|
|
74
|
+
end.not_to raise_error
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
specify 'predefned validatiors can be selected by string and symbols' do
|
|
78
|
+
expect do
|
|
79
|
+
Class.new(Qonfig::DataSet) do
|
|
80
|
+
validate 'a', :integer
|
|
81
|
+
validate 'b', 'integer', strict: true
|
|
82
|
+
end
|
|
83
|
+
end.not_to raise_error
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
specify 'dataset method validation (by:): fails on incorrect method name' do
|
|
87
|
+
expect do
|
|
88
|
+
# NOTE: only strings and symbols are supported
|
|
89
|
+
Class.new(Qonfig::DataSet) { validate by: 123 }
|
|
90
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
91
|
+
|
|
92
|
+
expect do
|
|
93
|
+
# NOTE: only strings and symbols are supported
|
|
94
|
+
Class.new(Qonfig::DataSet) { validate by: '123' }
|
|
95
|
+
end.not_to raise_error
|
|
96
|
+
|
|
97
|
+
expect do
|
|
98
|
+
# NOTE: only strings and symbols are supported
|
|
99
|
+
Class.new(Qonfig::DataSet) { validate by: :my_method }
|
|
100
|
+
end.not_to raise_error
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
specify 'you can set validation method that is not defined yet' do
|
|
104
|
+
expect do
|
|
105
|
+
Class.new(Qonfig::DataSet) do
|
|
106
|
+
validate by: :my_method # NOTE: not defined method
|
|
107
|
+
validate by: 'another_method' # NOTE: not defined method
|
|
108
|
+
end
|
|
109
|
+
end.not_to raise_error
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
specify 'correct setting key patterns' do
|
|
113
|
+
expect do
|
|
114
|
+
Class.new(Qonfig::DataSet) do
|
|
115
|
+
validate :db do # NOTE: symbol => correct
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
validate 'db.creds' do # NOTE: string => correct
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
validate :user, by: :my_method # NOTE: symbol => correct
|
|
122
|
+
validate 'password', by: :my_method # NOTE: string => correct
|
|
123
|
+
end
|
|
124
|
+
end.not_to raise_error
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
specify 'incorrect setting key patterns' do
|
|
128
|
+
expect do
|
|
129
|
+
Class.new(Qonfig::DataSet) do
|
|
130
|
+
validate 123, by: :my_method
|
|
131
|
+
end
|
|
132
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
133
|
+
|
|
134
|
+
expect do
|
|
135
|
+
Class.new(Qonfig::DataSet) do
|
|
136
|
+
validate 123 do
|
|
137
|
+
true
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
specify ':strict and non-strict both can be used' do
|
|
144
|
+
expect do
|
|
145
|
+
Class.new(Qonfig::DataSet) do
|
|
146
|
+
validate(:kek, strict: true) {}
|
|
147
|
+
validate(:pek, strict: false) {}
|
|
148
|
+
end
|
|
149
|
+
end.not_to raise_error
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
specify 'fails with error on non-boolean values of :strict attribute' do
|
|
153
|
+
expect do
|
|
154
|
+
Class.new(Qonfig::DataSet) do
|
|
155
|
+
validate(:check, strict: Object.new) {}
|
|
156
|
+
end
|
|
157
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
158
|
+
|
|
159
|
+
expect do
|
|
160
|
+
Class.new(Qonfig::DataSet) do
|
|
161
|
+
validate(:check, strict: nil) {}
|
|
162
|
+
end
|
|
163
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
describe 'validations' do
|
|
168
|
+
let(:config_klass) do
|
|
169
|
+
Class.new(Qonfig::DataSet) do
|
|
170
|
+
setting :telegraf_url, 'test' # NOTE: all right
|
|
171
|
+
|
|
172
|
+
# NOTE: check that telegraf_url is a string value
|
|
173
|
+
validate('telegraf_url', strict: true) do |value|
|
|
174
|
+
value.is_a?(String)
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
specify 'validates invalid settings on instnation' do
|
|
180
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
181
|
+
setting :telegraf_url, 12345 # NOTE: should be a string
|
|
182
|
+
validate 'telegraf_url' do |value|
|
|
183
|
+
value.is_a?(String)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
expect { config_klass.new }.to raise_error(Qonfig::ValidationError)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
specify 'validates settings defined by configuration options on instantiation' do
|
|
191
|
+
expect { config_klass.new(telegraf_url: '123') }.not_to raise_error
|
|
192
|
+
expect { config_klass.new(telegraf_url: 123) }.to raise_error(Qonfig::ValidationError)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
specify 'validates settings defined by configuration block' do
|
|
196
|
+
expect do
|
|
197
|
+
config_klass.new.configure do |config|
|
|
198
|
+
config.telegraf_url = 123 # NOTE: should be a string
|
|
199
|
+
end
|
|
200
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
specify 'validates settings setted in runtime' do
|
|
204
|
+
config = config_klass.new
|
|
205
|
+
|
|
206
|
+
expect { config.settings.telegraf_url = 1234 }.to raise_error(Qonfig::ValidationError)
|
|
207
|
+
expect { config.settings.telegraf_url = '55' }.not_to raise_error
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
specify 'invokes validations on config reload' do
|
|
211
|
+
# reload with hash
|
|
212
|
+
expect do
|
|
213
|
+
config_klass.new.reload!(telegraf_url: 123) # NOTE: should be a string
|
|
214
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
215
|
+
|
|
216
|
+
# reload with configuration block
|
|
217
|
+
expect do
|
|
218
|
+
config_klass.new.reload! do |conf|
|
|
219
|
+
conf.telegraf_url = 123 # NOTE: should be a string
|
|
220
|
+
end
|
|
221
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
specify 'invokes validations on config clearing' do
|
|
225
|
+
# NOTE:
|
|
226
|
+
# before #clear!: telegraf_config => 'test' (correct value)
|
|
227
|
+
# after #clear!: telegraf_config => nil (incorrect value)
|
|
228
|
+
|
|
229
|
+
expect { config_klass.new.clear! }.to raise_error(Qonfig::ValidationError)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
specify 'config state after exception interception (#valid? / #validate!)' do
|
|
233
|
+
config = config_klass.new
|
|
234
|
+
expect(config.valid?).to eq(true)
|
|
235
|
+
|
|
236
|
+
begin
|
|
237
|
+
config.clear! # NOTE: set telegraf_url to nil (to incorrect value)
|
|
238
|
+
rescue Qonfig::ValidationError
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
expect(config.valid?).to eq(false)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
specify 'deeply nested settings validation' do
|
|
245
|
+
deep_config_klass = Class.new(Qonfig::DataSet) do
|
|
246
|
+
setting :db do
|
|
247
|
+
setting :user, 'D@iVeR'
|
|
248
|
+
setting :password, 'test123'
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# NOTE: setting key pattern :)
|
|
252
|
+
validate('db.user') { |value| value.is_a?(String) }
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
# NOTE: all right (originally)
|
|
256
|
+
expect { deep_config_klass.new }.not_to raise_error
|
|
257
|
+
|
|
258
|
+
# NOTE: change validated setting to incorrect value
|
|
259
|
+
# rubocop:disable Layout/LineLength
|
|
260
|
+
expect { deep_config_klass.new(db: { user: 123 }) }.to raise_error(Qonfig::ValidationError)
|
|
261
|
+
expect { deep_config_klass.new.settings.db.user = 123 }.to raise_error(Qonfig::ValidationError)
|
|
262
|
+
# rubocop:enable Layout/LineLength
|
|
263
|
+
|
|
264
|
+
# NOTE: change non-validated setting to any value
|
|
265
|
+
expect { deep_config_klass.new(db: { password: 123 }) }.not_to raise_error
|
|
266
|
+
expect { deep_config_klass.new.settings.db.password = 555 }.not_to raise_error
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
specify 'child class inherits the base class validations' do
|
|
270
|
+
base_config_klass = Class.new(Qonfig::DataSet) do
|
|
271
|
+
setting :adapter, 'sidekiq'
|
|
272
|
+
validate(:adapter, strict: true) { |value| value.is_a?(String) }
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
child_config_klass = Class.new(base_config_klass) do
|
|
276
|
+
setting :enabled, false
|
|
277
|
+
validate('enabled') { |value| value.is_a?(TrueClass) || value.is_a?(FalseClass) }
|
|
278
|
+
|
|
279
|
+
# NOTE: should inherit :adapter valdations
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# NOTE: all right (originally)
|
|
283
|
+
expect { child_config_klass.new }.not_to raise_error
|
|
284
|
+
expect do
|
|
285
|
+
config = child_config_klass.new
|
|
286
|
+
config.settings.adapter = 'resque'
|
|
287
|
+
config.settings.enabled = true
|
|
288
|
+
end.not_to raise_error
|
|
289
|
+
|
|
290
|
+
# NOTE: inherited validations
|
|
291
|
+
# rubocop:disable Layout/LineLength
|
|
292
|
+
expect { child_config_klass.new(adapter: 123) }.to raise_error(Qonfig::ValidationError)
|
|
293
|
+
expect { child_config_klass.new.settings.adapter = 123 }.to raise_error(Qonfig::ValidationError)
|
|
294
|
+
expect { child_config_klass.new { |conf| conf.adapter = 123 } }.to raise_error(Qonfig::ValidationError)
|
|
295
|
+
expect { child_config_klass.new.reload!(adapter: 123) }.to raise_error(Qonfig::ValidationError)
|
|
296
|
+
# rubocop:enable Layout/LineLength
|
|
297
|
+
|
|
298
|
+
config = child_config_klass.new
|
|
299
|
+
expect(config.valid?).to eq(true)
|
|
300
|
+
begin
|
|
301
|
+
config.settings.adapter = 123
|
|
302
|
+
rescue Qonfig::ValidationError
|
|
303
|
+
end
|
|
304
|
+
expect(config.valid?).to eq(false)
|
|
305
|
+
expect(config.settings.adapter).to eq(123)
|
|
306
|
+
|
|
307
|
+
# NOTE: own validations
|
|
308
|
+
# rubocop:disable Layout/LineLength
|
|
309
|
+
expect { child_config_klass.new(enabled: '123') }.to raise_error(Qonfig::ValidationError)
|
|
310
|
+
expect { child_config_klass.new.settings.enabled = '123' }.to raise_error(Qonfig::ValidationError)
|
|
311
|
+
expect { child_config_klass.new { |conf| conf.enabled = '123' } }.to raise_error(Qonfig::ValidationError)
|
|
312
|
+
expect { child_config_klass.new.reload!(enabled: '123') }.to raise_error(Qonfig::ValidationError)
|
|
313
|
+
expect { child_config_klass.new.clear! }.to raise_error(Qonfig::ValidationError)
|
|
314
|
+
# rubocop:enable Layout/LineLength
|
|
315
|
+
|
|
316
|
+
config = child_config_klass.new
|
|
317
|
+
expect(config.valid?).to eq(true)
|
|
318
|
+
begin
|
|
319
|
+
config.settings.enabled = '123'
|
|
320
|
+
rescue Qonfig::ValidationError
|
|
321
|
+
end
|
|
322
|
+
expect(config.valid?).to eq(false)
|
|
323
|
+
expect(config.settings.enabled).to eq('123')
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
specify 'config composition inherits validators' do
|
|
327
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
328
|
+
setting :telegraf_url, 'udp://localhost:9094'
|
|
329
|
+
validate(:telegraf_url) { |value| value.is_a?(String) }
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
composed_config_klass = Class.new(Qonfig::DataSet) do
|
|
333
|
+
# NOTE: root configs
|
|
334
|
+
compose(config_klass)
|
|
335
|
+
|
|
336
|
+
# NOTE: nested configs
|
|
337
|
+
setting(:nested) { compose(config_klass) }
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# NOTE: all right
|
|
341
|
+
expect { composed_config_klass.new }.not_to raise_error
|
|
342
|
+
expect do
|
|
343
|
+
config = composed_config_klass.new
|
|
344
|
+
config.settings.telegraf_url = '123'
|
|
345
|
+
config.settings.nested.telegraf_url = '123'
|
|
346
|
+
end.not_to raise_error
|
|
347
|
+
|
|
348
|
+
expect do # NOTE: check root config validation
|
|
349
|
+
composed_config_klass.new.settings.telegraf_url = 123 # NOTE: should be a string
|
|
350
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
351
|
+
|
|
352
|
+
expect do # NOTE: check nested config validation
|
|
353
|
+
composed_config_klass.new.settings.nested.telegraf_url = 123
|
|
354
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
specify 'setting patterns (validation of a set of configs chosen by setting pattern)' do
|
|
358
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
359
|
+
setting :db do
|
|
360
|
+
setting :creds do
|
|
361
|
+
setting :user, 'D@iVeR'
|
|
362
|
+
setting :password, 'test123'
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
setting :sidekiq do
|
|
367
|
+
setting :admin do
|
|
368
|
+
setting :user, 'D@iVeR'
|
|
369
|
+
setting :password, '123test'
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
setting :logger_level, 'info'
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
setting :adapter, :resque
|
|
376
|
+
setting :port, 1019
|
|
377
|
+
|
|
378
|
+
# only the root setting key
|
|
379
|
+
# (port)
|
|
380
|
+
validate('port', strict: true) do |value|
|
|
381
|
+
value.is_a?(Numeric)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# all .user setting keys
|
|
385
|
+
# (db.creds.user, sidekiq.admin.user)
|
|
386
|
+
validate('#.user', strict: true) do |value|
|
|
387
|
+
value.is_a?(String)
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# one level inside db AND all password setting keys there
|
|
391
|
+
# (db.creds.password)
|
|
392
|
+
validate('db.*.password', strict: true) do |value|
|
|
393
|
+
value.is_a?(String)
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
# all .adapter setting keys
|
|
397
|
+
# (adapter)
|
|
398
|
+
validate('#.adapter', strict: true) do |value|
|
|
399
|
+
value.is_a?(Symbol)
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# all keys inside sidekiq setting group
|
|
403
|
+
# (sidekiq.admin.user, sidekiq.admin.password, sidekiq.logger_level)
|
|
404
|
+
validate('sidekiq.#', strict: true) do |value|
|
|
405
|
+
value.is_a?(String)
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
# NOTE: all right (originally)
|
|
410
|
+
expect { config_klass.new }.not_to raise_error
|
|
411
|
+
|
|
412
|
+
# rubocop:disable Layout/LineLength
|
|
413
|
+
expect { config_klass.new.settings.db.creds.user = 123 }.to raise_error(Qonfig::ValidationError)
|
|
414
|
+
expect { config_klass.new.settings.sidekiq.admin.user = 123 }.to raise_error(Qonfig::ValidationError)
|
|
415
|
+
expect { config_klass.new.settings.sidekiq.admin.password = 123 }.to raise_error(Qonfig::ValidationError)
|
|
416
|
+
expect { config_klass.new.settings.sidekiq.logger_level = nil }.to raise_error(Qonfig::ValidationError)
|
|
417
|
+
expect { config_klass.new.settings.db.creds.password = 123 }.to raise_error(Qonfig::ValidationError)
|
|
418
|
+
expect { config_klass.new.settings.adapter = 'que' }.to raise_error(Qonfig::ValidationError)
|
|
419
|
+
expect { config_klass.new.settings.port = '555' }.to raise_error(Qonfig::ValidationError)
|
|
420
|
+
# rubocop:enable Layout/LineLength
|
|
421
|
+
|
|
422
|
+
expect { config_klass.new.settings.db.creds.user = '123' }.not_to raise_error
|
|
423
|
+
expect { config_klass.new.settings.sidekiq.admin.user = '123' }.not_to raise_error
|
|
424
|
+
expect { config_klass.new.settings.sidekiq.admin.password = '123' }.not_to raise_error
|
|
425
|
+
expect { config_klass.new.settings.sidekiq.logger_level = 'warn' }.not_to raise_error
|
|
426
|
+
expect { config_klass.new.settings.db.creds.password = '123' }.not_to raise_error
|
|
427
|
+
expect { config_klass.new.settings.adapter = :que }.not_to raise_error
|
|
428
|
+
expect { config_klass.new.settings.port = 5599 }.not_to raise_error
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
specify 'proc-based validation wokrs inside dataset instance context' do
|
|
432
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
433
|
+
setting :some_key, 555
|
|
434
|
+
|
|
435
|
+
validate 'some_key' do |value|
|
|
436
|
+
value > some_method
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def some_method
|
|
440
|
+
123
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# NOTE: all right (originally)
|
|
445
|
+
expect { config_klass.new }.not_to raise_error
|
|
446
|
+
|
|
447
|
+
# NOTE: invalid value
|
|
448
|
+
expect { config_klass.new(some_key: 122) }.to raise_error(Qonfig::ValidationError)
|
|
449
|
+
# NOTE: valid value
|
|
450
|
+
expect { config_klass.new(some_key: 1234) }.not_to raise_error
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
specify 'setting key validation by custom method defined directly on dataset' do
|
|
454
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
455
|
+
setting :db do
|
|
456
|
+
setting :enabled, false
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# NOTE: validate setting keys by custom dataset method
|
|
460
|
+
validate 'db.#', by: :check_credentials
|
|
461
|
+
|
|
462
|
+
def check_credentials(setting_key_value)
|
|
463
|
+
setting_key_value.is_a?(TrueClass) || setting_key_value.is_a?(FalseClass)
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
# NOTE: all right (orginally)
|
|
468
|
+
expect { config_klass.new }.not_to raise_error
|
|
469
|
+
|
|
470
|
+
# NOTE: invalid values
|
|
471
|
+
expect { config_klass.new.settings.db.enabled = 123 }.to raise_error(Qonfig::ValidationError)
|
|
472
|
+
expect { config_klass.new(db: { enabled: 123 }) }.to raise_error(Qonfig::ValidationError)
|
|
473
|
+
|
|
474
|
+
# NOTE: valid values
|
|
475
|
+
expect { config_klass.new.settings.db.enabled = true }.not_to raise_error
|
|
476
|
+
expect { config_klass.new(db: { enabled: true }) }.not_to raise_error
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
specify 'full data set object validation via #validate' do
|
|
480
|
+
# валидация всего сеттингса скопом (синтаксис "validate { |settings| } / validate by:")
|
|
481
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
482
|
+
setting :namespace do
|
|
483
|
+
setting :enabled, :true
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
setting :go_for_cybersport, 'NO'
|
|
487
|
+
|
|
488
|
+
# NOTE: no setting key pattern => full dataset object validation
|
|
489
|
+
validate { settings.namespace.enabled.is_a?(Symbol) }
|
|
490
|
+
|
|
491
|
+
# NOTE: no setting key pattern => full dataset object validation
|
|
492
|
+
validate by: :check_all
|
|
493
|
+
|
|
494
|
+
def check_all
|
|
495
|
+
settings.go_for_cybersport == 'NO'
|
|
496
|
+
end
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
# NOTE: all right (originally)
|
|
500
|
+
expect { config_klass.new }.not_to raise_error
|
|
501
|
+
|
|
502
|
+
# NOTE: invalid values
|
|
503
|
+
# (namespace.enabled should be a symbol)
|
|
504
|
+
expect do
|
|
505
|
+
config_klass.new.settings.namespace.enabled = 123
|
|
506
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
507
|
+
# (go_for_cybersport should have the 'NO' string value)
|
|
508
|
+
expect do
|
|
509
|
+
config_klass.new.settings.go_for_cybersport = 'YES'
|
|
510
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
511
|
+
|
|
512
|
+
# NOTE: valid values
|
|
513
|
+
expect { config_klass.new.settings.namespace.enabled = :false }.not_to raise_error
|
|
514
|
+
expect { config_klass.new.settings.go_for_cybersport = 'NO' }.not_to raise_error
|
|
515
|
+
end
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
describe 'strict behaviour' do
|
|
519
|
+
specify 'non-strict by default (validation ignores nil values)' do
|
|
520
|
+
config = Qonfig::DataSet.build do
|
|
521
|
+
setting :login, 'D@iVeR'
|
|
522
|
+
setting :password, 'atata123'
|
|
523
|
+
setting :enabled, true
|
|
524
|
+
|
|
525
|
+
validate :login, :string
|
|
526
|
+
validate(:password) { |value| value.is_a?(String) }
|
|
527
|
+
validate :enabled, by: :check_enabled_setting
|
|
528
|
+
|
|
529
|
+
def check_enabled_setting(value)
|
|
530
|
+
value.is_a?(FalseClass) || value.is_a?(TrueClass)
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
expect(config.valid?).to eq(true)
|
|
535
|
+
expect { config.settings.login = nil }.not_to raise_error
|
|
536
|
+
expect { config.settings.password = nil }.not_to raise_error
|
|
537
|
+
expect { config.settings.enabled = nil }.not_to raise_error
|
|
538
|
+
expect(config.valid?).to eq(true)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
specify 'strict validation does not ignore nil value' do
|
|
542
|
+
config = Qonfig::DataSet.build do
|
|
543
|
+
setting :login, '0exp'
|
|
544
|
+
setting :password, 'test123'
|
|
545
|
+
setting :enabled, false
|
|
546
|
+
|
|
547
|
+
validate :login, :string, strict: true
|
|
548
|
+
validate(:password, strict: true) { |value| value.is_a?(String) }
|
|
549
|
+
validate :enabled, by: :check_enabled_setting, strict: true
|
|
550
|
+
|
|
551
|
+
def check_enabled_setting(value)
|
|
552
|
+
value.is_a?(FalseClass) || value.is_a?(TrueClass)
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
expect(config.valid?).to eq(true)
|
|
557
|
+
expect { config.settings.login = nil }.to raise_error(Qonfig::ValidationError)
|
|
558
|
+
expect { config.settings.password = nil }.to raise_error(Qonfig::ValidationError)
|
|
559
|
+
expect { config.settings.enabled = nil }.to raise_error(Qonfig::ValidationError)
|
|
560
|
+
expect(config.valid?).to eq(false)
|
|
561
|
+
end
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
describe 'predefined validators' do
|
|
565
|
+
specify 'common behaviour (strict)' do
|
|
566
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
567
|
+
setting :enabled, false
|
|
568
|
+
setting :count, 123
|
|
569
|
+
setting :amount, 23.55
|
|
570
|
+
setting :adapter, 'sidekiq'
|
|
571
|
+
setting :switcher, :on
|
|
572
|
+
setting :data, [1, 2, 3]
|
|
573
|
+
setting :mappings, a: 1, b: 2
|
|
574
|
+
setting :age, 20
|
|
575
|
+
|
|
576
|
+
validate :enabled, :boolean, strict: true
|
|
577
|
+
validate :count, :integer, strict: true
|
|
578
|
+
validate :amount, :float, strict: true
|
|
579
|
+
validate :adapter, :string, strict: true
|
|
580
|
+
validate :switcher, :symbol, strict: true
|
|
581
|
+
validate :data, :array, strict: true
|
|
582
|
+
validate :mappings, :hash, strict: true
|
|
583
|
+
validate :age, :numeric, strict: true
|
|
584
|
+
end
|
|
585
|
+
|
|
586
|
+
# NOTE: all right (originally)
|
|
587
|
+
expect { config_klass.new }.not_to raise_error
|
|
588
|
+
|
|
589
|
+
# NOTE: invalid values
|
|
590
|
+
expect { config_klass.new.settings.enabled = nil }.to raise_error(Qonfig::ValidationError)
|
|
591
|
+
expect { config_klass.new.settings.count = '5' }.to raise_error(Qonfig::ValidationError)
|
|
592
|
+
expect { config_klass.new.settings.amount = 22 }.to raise_error(Qonfig::ValidationError)
|
|
593
|
+
expect { config_klass.new.settings.adapter = :resque }.to raise_error(Qonfig::ValidationError)
|
|
594
|
+
expect { config_klass.new.settings.switcher = 'off' }.to raise_error(Qonfig::ValidationError)
|
|
595
|
+
expect { config_klass.new.settings.data = {} }.to raise_error(Qonfig::ValidationError)
|
|
596
|
+
expect { config_klass.new.settings.mappings = [] }.to raise_error(Qonfig::ValidationError)
|
|
597
|
+
expect { config_klass.new.settings.age = nil }.to raise_error(Qonfig::ValidationError)
|
|
598
|
+
|
|
599
|
+
# NOTE: valid values
|
|
600
|
+
expect { config_klass.new.settings.enabled = true }.not_to raise_error
|
|
601
|
+
expect { config_klass.new.settings.count = 5 }.not_to raise_error
|
|
602
|
+
expect { config_klass.new.settings.amount = 22.0 }.not_to raise_error
|
|
603
|
+
expect { config_klass.new.settings.adapter = 'resque' }.not_to raise_error
|
|
604
|
+
expect { config_klass.new.settings.switcher = :off }.not_to raise_error
|
|
605
|
+
expect { config_klass.new.settings.data = [] }.not_to raise_error
|
|
606
|
+
expect { config_klass.new.settings.mappings = {} }.not_to raise_error
|
|
607
|
+
expect { config_klass.new.settings.age = 20.1 }.not_to raise_error
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
specify 'common behaviour (non-strict)' do
|
|
611
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
612
|
+
setting :enabled, false
|
|
613
|
+
setting :count, 123
|
|
614
|
+
setting :amount, 23.55
|
|
615
|
+
setting :adapter, 'sidekiq'
|
|
616
|
+
setting :switcher, :on
|
|
617
|
+
setting :data, [1, 2, 3]
|
|
618
|
+
setting :mappings, a: 1, b: 2
|
|
619
|
+
setting :age, 20
|
|
620
|
+
|
|
621
|
+
validate :enabled, :boolean
|
|
622
|
+
validate :count, :integer
|
|
623
|
+
validate :amount, :float
|
|
624
|
+
validate :adapter, :string
|
|
625
|
+
validate :switcher, :symbol
|
|
626
|
+
validate :data, :array
|
|
627
|
+
validate :mappings, :hash
|
|
628
|
+
validate :age, :numeric
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
# NOTE: all right (originally)
|
|
632
|
+
expect { config_klass.new }.not_to raise_error
|
|
633
|
+
|
|
634
|
+
# NOTE: invalid values
|
|
635
|
+
expect { config_klass.new.settings.count = '5' }.to raise_error(Qonfig::ValidationError)
|
|
636
|
+
expect { config_klass.new.settings.amount = 22 }.to raise_error(Qonfig::ValidationError)
|
|
637
|
+
expect { config_klass.new.settings.adapter = :resque }.to raise_error(Qonfig::ValidationError)
|
|
638
|
+
expect { config_klass.new.settings.switcher = 'off' }.to raise_error(Qonfig::ValidationError)
|
|
639
|
+
expect { config_klass.new.settings.data = {} }.to raise_error(Qonfig::ValidationError)
|
|
640
|
+
expect { config_klass.new.settings.mappings = [] }.to raise_error(Qonfig::ValidationError)
|
|
641
|
+
|
|
642
|
+
# NOTE: non-strict values (validation ignores nil values)
|
|
643
|
+
expect { config_klass.new.settings.age = nil }.not_to raise_error
|
|
644
|
+
expect { config_klass.new.settings.enabled = nil }.not_to raise_error
|
|
645
|
+
|
|
646
|
+
# NOTE: valid values
|
|
647
|
+
expect { config_klass.new.settings.enabled = true }.not_to raise_error
|
|
648
|
+
expect { config_klass.new.settings.count = 5 }.not_to raise_error
|
|
649
|
+
expect { config_klass.new.settings.amount = 22.0 }.not_to raise_error
|
|
650
|
+
expect { config_klass.new.settings.adapter = 'resque' }.not_to raise_error
|
|
651
|
+
expect { config_klass.new.settings.switcher = :off }.not_to raise_error
|
|
652
|
+
expect { config_klass.new.settings.data = [] }.not_to raise_error
|
|
653
|
+
expect { config_klass.new.settings.mappings = {} }.not_to raise_error
|
|
654
|
+
expect { config_klass.new.settings.age = 20.1 }.not_to raise_error
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
describe 'valid_with?' do
|
|
658
|
+
specify '(#valid_with?): config object is valid or invalid with new potenital configs' do
|
|
659
|
+
config = Qonfig::DataSet.build do
|
|
660
|
+
setting :enabled, false
|
|
661
|
+
setting :count, 123
|
|
662
|
+
setting :amount, 23.55
|
|
663
|
+
setting :level, 100_500
|
|
664
|
+
setting :sound do
|
|
665
|
+
setting :genre, 'death-metal'
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
validate :enabled, :boolean
|
|
669
|
+
validate :count, :integer, strict: true
|
|
670
|
+
|
|
671
|
+
validate by: :check_level
|
|
672
|
+
validate 'sound.#' do |value|
|
|
673
|
+
value.is_a?(String)
|
|
674
|
+
end
|
|
675
|
+
|
|
676
|
+
def check_level
|
|
677
|
+
settings.level.is_a?(Numeric)
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
expect(config.valid_with?(
|
|
682
|
+
enabled: true,
|
|
683
|
+
count: 444,
|
|
684
|
+
amount: 66.21,
|
|
685
|
+
level: 123.55,
|
|
686
|
+
sound: { genre: 'melodic-death-metal' }
|
|
687
|
+
)).to eq(true)
|
|
688
|
+
|
|
689
|
+
expect(config.valid_with?(enabled: '123')).to eq(false)
|
|
690
|
+
expect(config.valid_with?(sound: { genre: false })).to eq(false)
|
|
691
|
+
expect(config.valid_with?(level: '2')).to eq(false)
|
|
692
|
+
expect(config.valid_with?(count: nil)).to eq(false)
|
|
693
|
+
expect(config.valid_with?(level: '7', count: nil, enabled: 123)).to eq(false)
|
|
694
|
+
|
|
695
|
+
# NOTE: check that original config does not mutated after validation checking
|
|
696
|
+
expect(config.settings.enabled).to eq(false)
|
|
697
|
+
expect(config.settings.count).to eq(123)
|
|
698
|
+
expect(config.settings.amount).to eq(23.55)
|
|
699
|
+
expect(config.settings.level).to eq(100_500)
|
|
700
|
+
expect(config.settings.sound.genre).to eq('death-metal')
|
|
701
|
+
end
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
specify '(.valid_with?/#valid_with?) support for do-config notation :)' do
|
|
705
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
706
|
+
setting :enabled, false
|
|
707
|
+
setting(:db) { setting :user, 'D@iVeR' }
|
|
708
|
+
validate :enabled, :boolean, strict: true
|
|
709
|
+
validate 'db.#', :text, strict: true
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
config = config_klass.new
|
|
713
|
+
|
|
714
|
+
# class-level checker
|
|
715
|
+
expect(
|
|
716
|
+
(config_klass.valid_with?(enabled: true) do |conf|
|
|
717
|
+
conf.db.user = '0exp'
|
|
718
|
+
end)
|
|
719
|
+
).to eq(true)
|
|
720
|
+
expect(
|
|
721
|
+
(config_klass.valid_with?(enabled: false) do |conf|
|
|
722
|
+
conf.db.user = 123
|
|
723
|
+
end)
|
|
724
|
+
).to eq(false)
|
|
725
|
+
expect(
|
|
726
|
+
(config_klass.valid_with?(enabled: nil) do |conf|
|
|
727
|
+
conf.db.user = 'test'
|
|
728
|
+
end)
|
|
729
|
+
).to eq(false)
|
|
730
|
+
|
|
731
|
+
# instance-level checker
|
|
732
|
+
expect(
|
|
733
|
+
(config.valid_with?(enabled: true) do |conf|
|
|
734
|
+
conf.db.user = '0exp'
|
|
735
|
+
end)
|
|
736
|
+
).to eq(true)
|
|
737
|
+
expect(
|
|
738
|
+
(config.valid_with?(enabled: false) do |conf|
|
|
739
|
+
conf.db.user = 123
|
|
740
|
+
end)
|
|
741
|
+
).to eq(false)
|
|
742
|
+
expect(
|
|
743
|
+
(config.valid_with?(enabled: nil) do |conf|
|
|
744
|
+
conf.db.user = 'test'
|
|
745
|
+
end)
|
|
746
|
+
).to eq(false)
|
|
747
|
+
|
|
748
|
+
# original instance is not changed
|
|
749
|
+
expect(config.settings.enabled).to eq(false)
|
|
750
|
+
expect(config.settings.db.user).to eq('D@iVeR')
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
specify '(.valid_with?) potential config instances will be valid or invalid with new configs' do
|
|
754
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
755
|
+
setting :enabled, false
|
|
756
|
+
setting :count, 123
|
|
757
|
+
setting :amount, 23.55
|
|
758
|
+
setting :level, 100_500
|
|
759
|
+
setting :sound do
|
|
760
|
+
setting :genre, 'death-metal'
|
|
761
|
+
end
|
|
762
|
+
|
|
763
|
+
validate :enabled, :boolean
|
|
764
|
+
validate :count, :integer, strict: true
|
|
765
|
+
|
|
766
|
+
validate by: :check_level
|
|
767
|
+
validate 'sound.#' do |value|
|
|
768
|
+
value.is_a?(String)
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
def check_level
|
|
772
|
+
settings.level.is_a?(Numeric)
|
|
773
|
+
end
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
expect(config_klass.valid_with?(
|
|
777
|
+
enabled: true,
|
|
778
|
+
count: 444,
|
|
779
|
+
amount: 66.21,
|
|
780
|
+
level: 123.55,
|
|
781
|
+
sound: { genre: 'melodic-death-metal' }
|
|
782
|
+
)).to eq(true)
|
|
783
|
+
|
|
784
|
+
expect(config_klass.valid_with?(enabled: '123')).to eq(false)
|
|
785
|
+
expect(config_klass.valid_with?(sound: { genre: false })).to eq(false)
|
|
786
|
+
expect(config_klass.valid_with?(level: '2')).to eq(false)
|
|
787
|
+
expect(config_klass.valid_with?(count: nil)).to eq(false)
|
|
788
|
+
expect(config_klass.valid_with?(level: '7', count: nil, enabled: 123)).to eq(false)
|
|
789
|
+
end
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
describe 'custom validators' do
|
|
793
|
+
specify 'you can define your own global validators and concrete-class-related validators' do
|
|
794
|
+
# custom global validator
|
|
795
|
+
Qonfig::DataSet.define_validator(:globality) do |value|
|
|
796
|
+
value == 'global'
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
config_klass = Class.new(Qonfig::DataSet) do
|
|
800
|
+
# custom class-related validator
|
|
801
|
+
define_validator(:int_or_sym) do |value|
|
|
802
|
+
value.is_a?(Integer) || value.is_a?(Symbol)
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
# custom class-related validator
|
|
806
|
+
define_validator(:queue_adapter) do |value|
|
|
807
|
+
value == :que || value == :sidekiq
|
|
808
|
+
end
|
|
809
|
+
|
|
810
|
+
setting :some_value, 123
|
|
811
|
+
setting :adapter, :sidekiq
|
|
812
|
+
setting :global, 'global'
|
|
813
|
+
|
|
814
|
+
validate :some_value, :int_or_sym # class-related validator
|
|
815
|
+
validate :adapter, :queue_adapter # class-related validator
|
|
816
|
+
validate :global, :globality, strict: true # global validator + srict cheker
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
expect { config_klass.new }.not_to raise_error
|
|
820
|
+
|
|
821
|
+
# invalid :global setting values
|
|
822
|
+
expect { config_klass.new(global: 123) }.to raise_error(Qonfig::ValidationError)
|
|
823
|
+
expect { config_klass.new(global: nil) }.to raise_error(Qonfig::ValidationError)
|
|
824
|
+
# invalid :some_value setting value
|
|
825
|
+
expect { config_klass.new(some_value: 123.456) }.to raise_error(Qonfig::ValidationError)
|
|
826
|
+
# invalid :adaper setting value
|
|
827
|
+
expect { config_klass.new(adapter: :sneakers) }.to raise_error(Qonfig::ValidationError)
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
specify 'fails when validation logic is not provided at definition step' do
|
|
831
|
+
config_klass = Class.new(Qonfig::DataSet)
|
|
832
|
+
|
|
833
|
+
expect do
|
|
834
|
+
config_klass.define_validator(:simple_validator)
|
|
835
|
+
end.to raise_error(Qonfig::ValidatorArgumentError)
|
|
836
|
+
|
|
837
|
+
expect do
|
|
838
|
+
config_klass.define_validator(:simple_validator) {}
|
|
839
|
+
end.not_to raise_error
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
specify 'inheritance works as expeced' do
|
|
843
|
+
Qonfig::DataSet.define_validator(:global_inheritable) do |value|
|
|
844
|
+
value == 0
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
first_klass = Class.new(Qonfig::DataSet) do
|
|
848
|
+
define_validator(:first_validator) { |value| value == 1 }
|
|
849
|
+
setting :a
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
second_klass = Class.new(first_klass) do
|
|
853
|
+
define_validator(:second_validator) { |value| value == 2 }
|
|
854
|
+
setting :b
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
third_klass = Class.new(second_klass) do
|
|
858
|
+
define_validator(:third_validator) { |value| value == 3 }
|
|
859
|
+
setting :c
|
|
860
|
+
setting :d
|
|
861
|
+
|
|
862
|
+
validate :a, :first_validator
|
|
863
|
+
validate :b, :second_validator
|
|
864
|
+
validate :c, :third_validator
|
|
865
|
+
validate :d, :global_inheritable
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
expect { third_klass.new(a: 1, b: 2, c: 3, d: 0) }.not_to raise_error
|
|
869
|
+
expect { third_klass.new }.not_to raise_error
|
|
870
|
+
|
|
871
|
+
expect { third_klass.new(a: '1') }.to raise_error(Qonfig::ValidationError)
|
|
872
|
+
expect { third_klass.new(b: '2') }.to raise_error(Qonfig::ValidationError)
|
|
873
|
+
expect { third_klass.new(c: '3') }.to raise_error(Qonfig::ValidationError)
|
|
874
|
+
expect { third_klass.new(d: '0') }.to raise_error(Qonfig::ValidationError)
|
|
875
|
+
end
|
|
876
|
+
|
|
877
|
+
specify 'predefined validators can be redefined' do
|
|
878
|
+
# custom global predefined validator
|
|
879
|
+
Qonfig::DataSet.define_validator(:global_predefined) do |value|
|
|
880
|
+
value == :predefined
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
config_klass_with_redefinition = Class.new(Qonfig::DataSet) do
|
|
884
|
+
define_validator(:global_predefined) do |value|
|
|
885
|
+
value == :class_level_predefined
|
|
886
|
+
end
|
|
887
|
+
|
|
888
|
+
setting :some_option
|
|
889
|
+
validate :some_option, :global_predefined
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
config_klass_without_redefinition = Class.new(Qonfig::DataSet) do
|
|
893
|
+
setting :some_option
|
|
894
|
+
validate :some_option, :global_predefined
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
# NOTE: config with redefined validator
|
|
898
|
+
expect do
|
|
899
|
+
# check that redefined validator is used
|
|
900
|
+
config_klass_with_redefinition.new(some_option: :class_level_predefined)
|
|
901
|
+
end.not_to raise_error
|
|
902
|
+
expect do
|
|
903
|
+
# check that global validator is not reached
|
|
904
|
+
config_klass_with_redefinition.new(some_option: :predefined)
|
|
905
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
906
|
+
|
|
907
|
+
# NOTE: config without redefined validator
|
|
908
|
+
expect do
|
|
909
|
+
config_klass_without_redefinition.new(some_option: :class_level_predefined)
|
|
910
|
+
end.to raise_error(Qonfig::ValidationError)
|
|
911
|
+
expect do
|
|
912
|
+
config_klass_without_redefinition.new(some_option: :predefined)
|
|
913
|
+
end.not_to raise_error
|
|
914
|
+
end
|
|
915
|
+
end
|
|
916
|
+
end
|