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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -2
  3. data/.rubocop.yml +19 -1
  4. data/.travis.yml +7 -2
  5. data/CHANGELOG.md +4 -0
  6. data/Gemfile.lock +102 -0
  7. data/README.md +2 -0
  8. data/gemfiles/with_external_deps.gemfile.lock +112 -0
  9. data/gemfiles/without_external_deps.gemfile.lock +102 -0
  10. data/lib/qonfig.rb +1 -1
  11. data/lib/qonfig/commands/definition/load_from_env.rb +2 -0
  12. data/lib/qonfig/commands/definition/load_from_env/value_converter.rb +2 -0
  13. data/lib/qonfig/imports/direct_key.rb +8 -2
  14. data/lib/qonfig/imports/mappings.rb +8 -2
  15. data/lib/qonfig/loaders/basic.rb +2 -0
  16. data/lib/qonfig/loaders/json.rb +2 -1
  17. data/lib/qonfig/settings.rb +5 -1
  18. data/lib/qonfig/settings/key_matcher.rb +1 -1
  19. data/lib/qonfig/uploaders/base.rb +2 -0
  20. data/lib/qonfig/uploaders/yaml.rb +2 -0
  21. data/lib/qonfig/version.rb +1 -1
  22. data/qonfig.gemspec +4 -6
  23. data/sig/.keep +0 -0
  24. data/spec/features/clear_options_spec.rb +92 -0
  25. data/spec/features/compacted_config_spec.rb +308 -0
  26. data/spec/features/composition_spec.rb +207 -0
  27. data/spec/features/config_definition_and_representation_spec.rb +535 -0
  28. data/spec/features/definition_order_spec.rb +69 -0
  29. data/spec/features/dig_functionality_spec.rb +47 -0
  30. data/spec/features/dot_notation_spec.rb +159 -0
  31. data/spec/features/export_settings_spec.rb +138 -0
  32. data/spec/features/expose_json_spec.rb +281 -0
  33. data/spec/features/expose_self/format_option_dynamic_spec.rb +69 -0
  34. data/spec/features/expose_self/format_option_json_spec.rb +74 -0
  35. data/spec/features/expose_self/format_option_unsupported_spec.rb +27 -0
  36. data/spec/features/expose_self/format_option_yaml_spec.rb +77 -0
  37. data/spec/features/expose_self_spec.rb +97 -0
  38. data/spec/features/expose_yaml_spec.rb +263 -0
  39. data/spec/features/freeze_state_spec.rb +122 -0
  40. data/spec/features/get_config_keys_spec.rb +62 -0
  41. data/spec/features/get_config_values_spec.rb +41 -0
  42. data/spec/features/has_a_key_spec.rb +48 -0
  43. data/spec/features/import_settings_spec.rb +323 -0
  44. data/spec/features/indifferent_access_spec.rb +57 -0
  45. data/spec/features/inheritance_spec.rb +110 -0
  46. data/spec/features/instantiation_without_class_definition_spec.rb +59 -0
  47. data/spec/features/iteration_over_setting_keys_spec.rb +48 -0
  48. data/spec/features/load_from_env_spec.rb +240 -0
  49. data/spec/features/load_from_json_spec.rb +97 -0
  50. data/spec/features/load_from_self/format_option_json_spec.rb +31 -0
  51. data/spec/features/load_from_self/format_option_unsupported_spec.rb +27 -0
  52. data/spec/features/load_from_self/format_option_yaml_spec.rb +49 -0
  53. data/spec/features/load_from_self/with_erb_instructions_spec.rb +33 -0
  54. data/spec/features/load_from_self/with_hash_like_data_representation_spec.rb +66 -0
  55. data/spec/features/load_from_self/with_non_hash_like_data_representation_spec.rb +19 -0
  56. data/spec/features/load_from_self/without_end_data_spec.rb +11 -0
  57. data/spec/features/load_from_yaml_spec.rb +110 -0
  58. data/spec/features/load_setting_values_from_file/by_instance_method_examples.rb +171 -0
  59. data/spec/features/load_setting_values_from_file/by_macros_examples.rb +165 -0
  60. data/spec/features/load_setting_values_from_file/load_from_json_spec.rb +21 -0
  61. data/spec/features/load_setting_values_from_file/load_from_self/json_format/end_data_with_env_spec.rb +100 -0
  62. data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_end_data_spec.rb +129 -0
  63. data/spec/features/load_setting_values_from_file/load_from_self/json_format/with_incorrect_end_data_spec.rb +34 -0
  64. data/spec/features/load_setting_values_from_file/load_from_self/json_format/without_end_data_spec.rb +65 -0
  65. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/end_data_with_env_spec.rb +94 -0
  66. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_end_data_spec.rb +126 -0
  67. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/with_incorrect_end_data_spec.rb +32 -0
  68. data/spec/features/load_setting_values_from_file/load_from_self/yaml_format/without_end_data_spec.rb +65 -0
  69. data/spec/features/load_setting_values_from_file/load_from_yaml_spec.rb +21 -0
  70. data/spec/features/load_setting_values_from_file/shared_behavior_spec.rb +33 -0
  71. data/spec/features/mixin_spec.rb +387 -0
  72. data/spec/features/non_redefineable_core_methods_spec.rb +29 -0
  73. data/spec/features/plugins/pretty_print_spec.rb +86 -0
  74. data/spec/features/plugins/toml/expose_self/format_option_toml_spec.rb +71 -0
  75. data/spec/features/plugins/toml/expose_toml_spec.rb +221 -0
  76. data/spec/features/plugins/toml/load_from_self/format_option_toml_spec.rb +27 -0
  77. data/spec/features/plugins/toml/load_from_toml_spec.rb +109 -0
  78. data/spec/features/plugins/toml/load_setting_values_from_file/load_from_toml_spec.rb +27 -0
  79. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/end_data_with_env_spec.rb +95 -0
  80. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_end_data_spec.rb +125 -0
  81. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/with_incorrect_end_data_spec.rb +34 -0
  82. data/spec/features/plugins/toml/load_setting_values_from_file/load_toml_from_self/without_end_data_spec.rb +65 -0
  83. data/spec/features/plugins/toml/load_setting_values_from_file/shared_behavior_spec.rb +34 -0
  84. data/spec/features/plugins/toml/save_to_toml_spec.rb +149 -0
  85. data/spec/features/plugins/vault/expose_vault_spec.rb +117 -0
  86. data/spec/features/plugins/vault/load_from_vault_spec.rb +80 -0
  87. data/spec/features/plugins_spec.rb +89 -0
  88. data/spec/features/reload_spec.rb +75 -0
  89. data/spec/features/run_code_with_temporary_settings_spec.rb +104 -0
  90. data/spec/features/save_to_file/save_to_json_spec.rb +157 -0
  91. data/spec/features/save_to_file/save_to_yaml_spec.rb +189 -0
  92. data/spec/features/settings_as_predicates_spec.rb +47 -0
  93. data/spec/features/settings_redefinition_spec.rb +30 -0
  94. data/spec/features/slice_functionality_spec.rb +69 -0
  95. data/spec/features/subset_functionality_spec.rb +49 -0
  96. data/spec/features/validation_spec.rb +916 -0
  97. data/spec/fixtures/array_settings.yml +3 -0
  98. data/spec/fixtures/expose_json/incompatible_root_structure.json +6 -0
  99. data/spec/fixtures/expose_json/incompatible_structure.json +4 -0
  100. data/spec/fixtures/expose_json/project.development.json +7 -0
  101. data/spec/fixtures/expose_json/project.json +30 -0
  102. data/spec/fixtures/expose_json/project.production.json +7 -0
  103. data/spec/fixtures/expose_json/project.staging.json +7 -0
  104. data/spec/fixtures/expose_json/project.test.json +7 -0
  105. data/spec/fixtures/expose_yaml/incompatible_structure.yml +2 -0
  106. data/spec/fixtures/expose_yaml/project.development.yml +4 -0
  107. data/spec/fixtures/expose_yaml/project.production.yml +4 -0
  108. data/spec/fixtures/expose_yaml/project.staging.yml +4 -0
  109. data/spec/fixtures/expose_yaml/project.test.yml +4 -0
  110. data/spec/fixtures/expose_yaml/project.yml +25 -0
  111. data/spec/fixtures/json_array_sample.json +14 -0
  112. data/spec/fixtures/json_object_sample.json +9 -0
  113. data/spec/fixtures/json_with_empty_object.json +6 -0
  114. data/spec/fixtures/json_with_erb.json +6 -0
  115. data/spec/fixtures/plugins/toml/expose_toml/project.development.toml +4 -0
  116. data/spec/fixtures/plugins/toml/expose_toml/project.production.toml +4 -0
  117. data/spec/fixtures/plugins/toml/expose_toml/project.staging.toml +4 -0
  118. data/spec/fixtures/plugins/toml/expose_toml/project.test.toml +4 -0
  119. data/spec/fixtures/plugins/toml/expose_toml/project.toml +27 -0
  120. data/spec/fixtures/plugins/toml/mini_file.toml +6 -0
  121. data/spec/fixtures/plugins/toml/toml_sample_with_all_types.toml +72 -0
  122. data/spec/fixtures/plugins/toml/values_file/with_env.toml +13 -0
  123. data/spec/fixtures/plugins/toml/values_file/without_env.toml +6 -0
  124. data/spec/fixtures/rubocop_settings.yml +12 -0
  125. data/spec/fixtures/shared_settings_with_aliases.yml +10 -0
  126. data/spec/fixtures/travis_settings.yml +6 -0
  127. data/spec/fixtures/values_file/with_env.json +19 -0
  128. data/spec/fixtures/values_file/with_env.yml +17 -0
  129. data/spec/fixtures/values_file/without_env.json +8 -0
  130. data/spec/fixtures/values_file/without_env.yml +5 -0
  131. data/spec/fixtures/with_empty_hash.yml +4 -0
  132. data/spec/fixtures/with_erb_instructions.yml +3 -0
  133. data/spec/spec_helper.rb +27 -0
  134. data/spec/support/meta_scopes.rb +20 -0
  135. data/spec/support/spec_support.rb +42 -0
  136. metadata +128 -11
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Plugins(vault): expose vault', plugin: :vault do
4
+ before { stub_const('VaultConfig', vault_class) }
5
+
6
+ before { allow(Vault).to receive(:logical).and_return(logical_double) }
7
+
8
+ let(:logical_double) { instance_double(Vault::Logical) }
9
+
10
+ let(:returned_data) do
11
+ instance_double(Vault::Secret).tap do |instance|
12
+ allow(instance).to receive(:data).and_return(secret_data)
13
+ end
14
+ end
15
+ let(:secret_data) do
16
+ { data: { production: { kek: 'pek', cheburek: true }, other_key: '<%= 1 + 1 %>' } }
17
+ end
18
+
19
+ let(:vault_class) do
20
+ Class.new(Qonfig::DataSet) do
21
+ setting :based_on_path do
22
+ expose_vault 'kv/data/path_based', via: :path, env: :production
23
+ end
24
+
25
+ setting :based_on_env_key do
26
+ expose_vault 'kv/data/env_key', via: :env_key, env: 'production'
27
+ end
28
+ end
29
+ end
30
+
31
+ specify 'defines config object by vault instructions and specific environment settings' do
32
+ expect(Vault.logical).to(
33
+ receive(:read).with('kv/data/production/path_based').and_return(returned_data)
34
+ )
35
+ expect(Vault.logical).to receive(:read).with('kv/data/env_key').and_return(returned_data)
36
+
37
+ VaultConfig.new.settings.tap do |conf|
38
+ expect(conf.based_on_path.other_key).to eq(2)
39
+ expect(conf.based_on_path.production).to be_a(Qonfig::Settings)
40
+ expect(conf.based_on_env_key).to have_attributes(kek: 'pek', cheburek: true)
41
+ end
42
+ end
43
+
44
+ context 'when provided env argument is an Object' do
45
+ specify 'raises an error' do
46
+ expect do
47
+ Class.new(Qonfig::DataSet) do
48
+ expose_vault 'kv/data/path_based', via: Object.new, env: :production
49
+ end
50
+ end.to raise_error(Qonfig::ArgumentError)
51
+ end
52
+ end
53
+
54
+ context 'when provided via argument is an Object' do
55
+ specify 'raises an error' do
56
+ expect do
57
+ Class.new(Qonfig::DataSet) do
58
+ expose_vault 'kv/data/path_based', via: :path, env: Object.new
59
+ end
60
+ end.to raise_error(Qonfig::ArgumentError)
61
+ end
62
+ end
63
+
64
+ context 'when provided via is not supported' do
65
+ specify 'raises an error' do
66
+ expect do
67
+ Class.new(Qonfig::DataSet) do
68
+ expose_vault 'kv/data/path_based', via: :kek, env: :production
69
+ end
70
+ end.to raise_error(Qonfig::ArgumentError)
71
+ end
72
+ end
73
+
74
+ context 'when provided env is empty' do
75
+ specify 'raises an error' do
76
+ expect do
77
+ Class.new(Qonfig::DataSet) do
78
+ expose_vault 'kv/data/path_based', via: :path, env: ''
79
+ end
80
+ end.to raise_error(Qonfig::ArgumentError)
81
+ end
82
+ end
83
+
84
+ context "when provided key doesn't exist" do
85
+ let(:vault_class) do
86
+ Class.new(Qonfig::DataSet) do
87
+ expose_vault 'kv/data/env_key', via: :env_key, env: 'kekduction'
88
+ end
89
+ end
90
+
91
+ specify 'raises an error' do
92
+ expect(Vault.logical).to receive(:read).with('kv/data/env_key').and_return(returned_data)
93
+
94
+ expect { VaultConfig.new }.to raise_error(/does not contain settings with <kekduction>/)
95
+ end
96
+ end
97
+
98
+ context 'with not strict mode' do
99
+ let(:vault_class) do
100
+ Class.new(Qonfig::DataSet) do
101
+ setting :based_on_env_key do
102
+ expose_vault 'kv/data/env_key', via: :env_key, env: 'production', strict: false
103
+ end
104
+ end
105
+ end
106
+
107
+ let(:secret_data) { Hash[] }
108
+
109
+ specify "doesn't fail and uses empty config" do
110
+ expect(Vault.logical).to receive(:read).with('kv/data/env_key').and_return(returned_data)
111
+
112
+ conf = nil
113
+ expect { conf = VaultConfig.new }.not_to raise_error
114
+ expect(conf.to_h['based_on_env_key']).to be_empty
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Plugins(vault): Load from vault kv store', plugin: :vault do
4
+ before { stub_const('VaultConfig', vault_class) }
5
+
6
+ before { allow(Vault).to receive(:logical).and_return(logical_double) }
7
+
8
+ let(:returned_data) do
9
+ instance_double(Vault::Secret).tap do |instance|
10
+ allow(instance).to receive(:data).and_return(secret_data)
11
+ end
12
+ end
13
+ let(:logical_double) { instance_double(Vault::Logical) }
14
+ let(:secret_data) { Hash[data: { kek: true, pek: 'cheburek', nested: Hash[key: 123] }] }
15
+
16
+ let(:vault_class) do
17
+ Class.new(Qonfig::DataSet) do
18
+ load_from_vault 'kv/data/development'
19
+ end
20
+ end
21
+
22
+ specify 'defines config object by vault instructions' do
23
+ expect(Vault.logical).to receive(:read).with('kv/data/development').and_return(returned_data)
24
+
25
+ VaultConfig.new.settings.tap do |conf|
26
+ expect(conf).to have_attributes(kek: true, pek: 'cheburek')
27
+ expect(conf.nested.key).to eq(123)
28
+ end
29
+ end
30
+
31
+ context 'with not exist path' do
32
+ let(:expected_error_args) do
33
+ [Qonfig::FileNotFoundError, 'No such file or directory - Path kv/data/development not exist']
34
+ end
35
+
36
+ specify 'raises error' do
37
+ expect(Vault.logical).to receive(:read).with('kv/data/development').and_return(nil)
38
+ expect { VaultConfig.new }.to raise_error(*expected_error_args)
39
+ end
40
+ end
41
+
42
+ context 'with Pathname at path argument' do
43
+ let(:vault_class) do
44
+ Class.new(Qonfig::DataSet) do
45
+ load_from_vault Pathname('kv/data/development')
46
+ end
47
+ end
48
+
49
+ specify 'converts it to string' do
50
+ expect(Vault.logical).to receive(:read).with('kv/data/development').and_return(returned_data)
51
+
52
+ VaultConfig.new
53
+ end
54
+ end
55
+
56
+ context 'when strict set to false' do
57
+ let(:vault_class) do
58
+ Class.new(Qonfig::DataSet) do
59
+ load_from_vault 'kv/data/development', strict: false
60
+ end
61
+ end
62
+
63
+ specify "doesn't fail and uses empty config" do
64
+ expect(Vault.logical).to receive(:read).with('kv/data/development').and_return(nil).twice
65
+
66
+ expect { VaultConfig.new }.not_to raise_error
67
+ expect(VaultConfig.new.to_h).to eq({})
68
+ end
69
+ end
70
+
71
+ context 'when VaultError is raised' do
72
+ let(:raised_error) { Vault::VaultError.new('Cool error') }
73
+
74
+ specify 'raises VaultLoaderError' do
75
+ expect(Vault.logical).to receive(:read).with('kv/data/development').and_raise(raised_error)
76
+
77
+ expect { VaultConfig.new }.to raise_error(Qonfig::VaultLoaderError, 'Cool error')
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Plugins' do
4
+ specify 'plguin regsitration, load and resolving' do
5
+ # plugins are not registered
6
+ expect(Qonfig::Plugins.names).not_to include('internal_test_plugin', 'external_test_plugin')
7
+ expect(Qonfig.plugins).not_to include('internal_test_plugin', 'external_test_plugin')
8
+
9
+ InternalTestPluginInterceptor = Class.new { def self.invoke; end }
10
+ ExternalTestPluginInterceptor = Class.new { def self.call; end }
11
+
12
+ module Qonfig::Plugins
13
+ class InternalTestPlugin < Abstract
14
+ def self.install!
15
+ InternalTestPluginInterceptor.invoke
16
+ end
17
+ end
18
+
19
+ class ExternalTestPlugin < Abstract
20
+ def self.install!
21
+ ExternalTestPluginInterceptor.call
22
+ end
23
+ end
24
+
25
+ # register new plugins
26
+ register_plugin(:internal_test_plugin, InternalTestPlugin)
27
+ register_plugin(:external_test_plugin, ExternalTestPlugin)
28
+ end
29
+
30
+ # plugins are registered
31
+ expect(Qonfig::Plugins.names).to include('internal_test_plugin', 'external_test_plugin')
32
+ expect(Qonfig.plugins).to include('internal_test_plugin', 'external_test_plugin')
33
+
34
+ # new plugins is not included in #loaded_plugins list
35
+ expect(Qonfig.loaded_plugins).not_to include('internal_test_plugin')
36
+ expect(Qonfig.loaded_plugins).not_to include('external_test_plugin')
37
+ expect(Qonfig.enabled_plugins).not_to include('internal_test_plugin')
38
+ expect(Qonfig.enabled_plugins).not_to include('external_test_plugin')
39
+ expect(Qonfig.loaded_plugins).to eq(Qonfig.enabled_plugins)
40
+
41
+ # plugin can be loaded
42
+ expect(InternalTestPluginInterceptor).to receive(:invoke).exactly(4).times
43
+ Qonfig::Plugins.load(:internal_test_plugin)
44
+ Qonfig::Plugins.load('internal_test_plugin')
45
+ Qonfig.plugin(:internal_test_plugin)
46
+ Qonfig.plugin('internal_test_plugin')
47
+ expect(Qonfig.loaded_plugins).to include('internal_test_plugin')
48
+ expect(Qonfig.loaded_plugins).not_to include('external_test_plugin')
49
+ expect(Qonfig.enabled_plugins).to include('internal_test_plugin')
50
+ expect(Qonfig.enabled_plugins).not_to include('external_test_plugin')
51
+ expect(Qonfig.loaded_plugins).to eq(Qonfig.enabled_plugins)
52
+
53
+ # plugin can be loaded
54
+ expect(ExternalTestPluginInterceptor).to receive(:call).exactly(4).times
55
+ Qonfig::Plugins.load(:external_test_plugin)
56
+ Qonfig::Plugins.load('external_test_plugin')
57
+ Qonfig.enable(:external_test_plugin)
58
+ Qonfig.enable('external_test_plugin')
59
+ expect(Qonfig.loaded_plugins).to include('external_test_plugin')
60
+ expect(Qonfig.loaded_plugins).to include('internal_test_plugin')
61
+ expect(Qonfig.enabled_plugins).to include('external_test_plugin')
62
+ expect(Qonfig.enabled_plugins).to include('internal_test_plugin')
63
+ expect(Qonfig.loaded_plugins).to eq(Qonfig.enabled_plugins)
64
+
65
+ # fails when there is an attempt to register a plugin with already used name
66
+ expect do
67
+ module Qonfig::Plugins
68
+ register_plugin(:internal_test_plugin, Object)
69
+ end
70
+ end.to raise_error(Qonfig::AlreadyRegisteredPluginError)
71
+
72
+ # fails when there is an attempt to register a plugin with already used name
73
+ expect do
74
+ module Qonfig::Plugins
75
+ register_plugin(:external_test_plugin, Object)
76
+ end
77
+ end.to raise_error(Qonfig::AlreadyRegisteredPluginError)
78
+
79
+ # fails when there is an attempt to load an unregistered plugin
80
+ expect do
81
+ Qonfig::Plugins.load(:kek_test_plugin)
82
+ end.to raise_error(Qonfig::UnregisteredPluginError)
83
+
84
+ # fails when there is an attempt to load an unregistered plugin
85
+ expect do
86
+ Qonfig.plugin(:kek_test_plugin)
87
+ end.to raise_error(Qonfig::UnregisteredPluginError)
88
+ end
89
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Config reloading' do
4
+ specify 'config reloading works correctly' do
5
+ class ReloadableConfig < Qonfig::DataSet
6
+ setting :db do
7
+ setting :adapter, 'postgresql'
8
+ end
9
+
10
+ setting :logging, false
11
+ end
12
+
13
+ config = ReloadableConfig.new
14
+
15
+ expect(config.to_h).to match(
16
+ 'db' => { 'adapter' => 'postgresql' },
17
+ 'logging' => false
18
+ )
19
+
20
+ config.configure { |conf| conf.logging = true } # change internal state
21
+
22
+ # re-define and append settings and validations
23
+ class ReloadableConfig
24
+ setting :db do
25
+ setting :adapter, 'mongoid' # re-define defaults
26
+ end
27
+
28
+ setting :enable_api, false # append new setting
29
+
30
+ validate :logging, :boolean, strict: true
31
+ end
32
+
33
+ expect(config.to_h).to match(
34
+ 'db' => { 'adapter' => 'postgresql' },
35
+ 'logging' => true # internal state has initial value (not a changed previously)
36
+ )
37
+
38
+ # new validator is not invoked (logging should be a boolean)
39
+ expect { config.settings.logging = nil }.not_to raise_error
40
+
41
+ # reload config settings
42
+ config.reload!
43
+
44
+ expect(config.to_h).to match(
45
+ 'db' => { 'adapter' => 'mongoid' },
46
+ 'logging' => false,
47
+ 'enable_api' => false
48
+ )
49
+
50
+ # reload with instant configuration
51
+ config.reload! do |conf|
52
+ conf.enable_api = true # changed instantly
53
+ end
54
+
55
+ expect(config.to_h).to match(
56
+ 'db' => { 'adapter' => 'mongoid' },
57
+ 'logging' => false,
58
+ 'enable_api' => true # value from isntant change
59
+ )
60
+
61
+ # reload with hash && proc configuration
62
+ config.reload!(db: { adapter: 'oracloid' }) do |conf|
63
+ conf.enable_api = true
64
+ end
65
+
66
+ expect(config.to_h).to match(
67
+ 'db' => { 'adapter' => 'oracloid' },
68
+ 'logging' => false,
69
+ 'enable_api' => true
70
+ )
71
+
72
+ # reload and set invalid options (logging cant be nil)
73
+ expect { config.reload!(logging: nil) }.to raise_error(Qonfig::ValidationError)
74
+ end
75
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Run code with temporary settings' do
4
+ specify 'temporary settings works as expected :)' do
5
+ config = Qonfig::DataSet.build do
6
+ setting :api do
7
+ setting :token, 'test123'
8
+ setting :login, 'D@iVeR'
9
+ end
10
+ end
11
+
12
+ config.with(api: { token: '123test' }) do
13
+ config.settings.api.login = '555'
14
+
15
+ # NOTE: settings was changed
16
+ expect(config.settings.api.token).to eq('123test')
17
+ expect(config.settings.api.login).to eq('555')
18
+ end
19
+
20
+ # NOTE: original settings are still original :)
21
+ expect(config.settings.api.token).to eq('test123')
22
+ expect(config.settings.api.login).to eq('D@iVeR')
23
+ end
24
+
25
+ specify 'thread-safety' do
26
+ config = Qonfig::DataSet.build do
27
+ setting :api do
28
+ setting :token, 'test123'
29
+ setting :login, 'D@iVeR'
30
+ end
31
+
32
+ setting :credentials do
33
+ setting :user, 'admin'
34
+ setting :password, '1234asdf'
35
+ end
36
+ end
37
+
38
+ ThreadGroup.new.tap do |thread_group|
39
+ 10.times do
40
+ thread_group.add(Thread.new do
41
+ # NOTE: change settings temporary
42
+ config.with(api: { token: '777555' }, credentials: { password: 'test123' }) do
43
+ config.settings.credentials.user = 'nimda'
44
+ end
45
+ end)
46
+
47
+ thread_group.add(Thread.new do
48
+ # NOTE: settings are not changed :)
49
+ expect(config.settings.credentials.user).to eq('admin')
50
+ expect(config.settings.credentials.password).to eq('1234asdf')
51
+ expect(config.settings.api.token).to eq('test123')
52
+ expect(config.settings.api.login).to eq('D@iVeR')
53
+ end)
54
+
55
+ thread_group.add(Thread.new do
56
+ # NOTE: change settings temporary
57
+ config.with do
58
+ config.settings.api.login = 'provider'
59
+ config.settings.api.token = 'super_puper_123'
60
+ end
61
+ end)
62
+
63
+ thread_group.add(Thread.new do
64
+ # NOTE: settings are not changed :)
65
+ expect(config.settings.credentials.user).to eq('admin')
66
+ expect(config.settings.credentials.password).to eq('1234asdf')
67
+ expect(config.settings.api.token).to eq('test123')
68
+ expect(config.settings.api.login).to eq('D@iVeR')
69
+ end)
70
+
71
+ thread_group.add(Thread.new do
72
+ config.with(api: { login: '0exp' }, credentials: { user: 'D@iVeR' }) do
73
+ config.settings.api.token = 'kekpek123'
74
+ config.settings.credentials.password = 'admin'
75
+ end
76
+ end)
77
+
78
+ thread_group.add(Thread.new do
79
+ # NOTE: settings are not changed :)
80
+ expect(config.settings.credentials.user).to eq('admin')
81
+ expect(config.settings.credentials.password).to eq('1234asdf')
82
+ expect(config.settings.api.token).to eq('test123')
83
+ expect(config.settings.api.login).to eq('D@iVeR')
84
+ end)
85
+
86
+ thread_group.add(Thread.new do
87
+ # NOTE: change settings temporary
88
+ config.with(api: { login: 'mobile_legends' }, credentials: { user: 'dota2' }) do
89
+ config.settings.api.token = 'league_of_legends'
90
+ config.settings.credentials.password = 'overwatch'
91
+ end
92
+ end)
93
+
94
+ thread_group.add(Thread.new do
95
+ # NOTE: settings are not changed :)
96
+ expect(config.settings.credentials.user).to eq('admin')
97
+ expect(config.settings.credentials.password).to eq('1234asdf')
98
+ expect(config.settings.api.token).to eq('test123')
99
+ expect(config.settings.api.login).to eq('D@iVeR')
100
+ end)
101
+ end
102
+ end.list.map(&:join)
103
+ end
104
+ end