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,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe '#expose_self => format: :dynamic' do
4
+ specify ':dynamic-format - automatically resolves the data format' do
5
+ class ExposeEndDataFormatDynamicallyConfig < Qonfig::DataSet
6
+ setting(:staging_env) { expose_self env: :staging }
7
+ setting(:prod_env) { expose_self env: :production }
8
+ setting(:test_env) { expose_self env: :test }
9
+ end
10
+
11
+ config = ExposeEndDataFormatDynamicallyConfig.new
12
+
13
+ # NOTE: production env
14
+ expect(config.settings.prod_env.credentials.user).to eq('admin')
15
+ expect(config.settings.prod_env.credentials.password).to eq('123')
16
+ expect(config.settings.prod_env.credentials.enabled).to eq(true)
17
+ expect(config.settings.prod_env.api).to eq('google.com')
18
+ expect(config.settings.prod_env.ports).to eq([10001, 10002, 10003])
19
+
20
+ # NOTE: test env
21
+ expect(config.settings.test_env.credentials.user).to eq('megaman')
22
+ expect(config.settings.test_env.credentials.password).to eq('atata123')
23
+ expect(config.settings.test_env.credentials.enabled).to eq(false)
24
+ expect(config.settings.test_env.api).to eq('yandex.ru')
25
+ expect(config.settings.test_env.ports).to eq([1, 2, 3])
26
+
27
+ # NOTE: staging env
28
+ expect(config.settings.staging_env.credentials.user).to eq('diablo')
29
+ expect(config.settings.staging_env.credentials.password).to eq('testornot')
30
+ expect(config.settings.staging_env.credentials.enabled).to eq(true)
31
+ expect(config.settings.staging_env.api).to eq('battle.net')
32
+ expect(config.settings.staging_env.ports).to eq([111, 222, 333])
33
+ end
34
+ end
35
+
36
+ __END__
37
+
38
+ production:
39
+ credentials:
40
+ user: admin
41
+ password: '123'
42
+ enabled: true
43
+ api: google.com
44
+ ports:
45
+ - 10001
46
+ - 10002
47
+ - 10003
48
+
49
+ test:
50
+ credentials:
51
+ user: megaman
52
+ password: atata123
53
+ enabled: false
54
+ api: yandex.ru
55
+ ports:
56
+ - 1
57
+ - 2
58
+ - 3
59
+
60
+ staging:
61
+ credentials:
62
+ user: diablo
63
+ password: testornot
64
+ enabled: true
65
+ api: battle.net
66
+ ports:
67
+ - 111
68
+ - 222
69
+ - 333
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe '#expose_self => format: :json' do
4
+ specify ':json-format support' do
5
+ class ExposeJsonEndDataConfig < Qonfig::DataSet
6
+ setting :staging_env do
7
+ expose_self format: :json, env: :staging
8
+ end
9
+
10
+ setting :prod_env do
11
+ expose_self format: :json, env: :production
12
+ end
13
+
14
+ setting :test_env do
15
+ expose_self format: :json, env: :test
16
+ end
17
+ end
18
+
19
+ config = ExposeJsonEndDataConfig.new
20
+
21
+ # NOTE: production env
22
+ expect(config.settings.prod_env.credentials.user).to eq('admin')
23
+ expect(config.settings.prod_env.credentials.password).to eq('123')
24
+ expect(config.settings.prod_env.credentials.enabled).to eq(true)
25
+ expect(config.settings.prod_env.api).to eq('google.com')
26
+ expect(config.settings.prod_env.ports).to eq([10001, 10002, 10003])
27
+
28
+ # NOTE: test env
29
+ expect(config.settings.test_env.credentials.user).to eq('megaman')
30
+ expect(config.settings.test_env.credentials.password).to eq('atata123')
31
+ expect(config.settings.test_env.credentials.enabled).to eq(false)
32
+ expect(config.settings.test_env.api).to eq('yandex.ru')
33
+ expect(config.settings.test_env.ports).to eq([1, 2, 3])
34
+
35
+ # NOTE: staging env
36
+ expect(config.settings.staging_env.credentials.user).to eq('diablo')
37
+ expect(config.settings.staging_env.credentials.password).to eq('testornot')
38
+ expect(config.settings.staging_env.credentials.enabled).to eq(true)
39
+ expect(config.settings.staging_env.api).to eq('battle.net')
40
+ expect(config.settings.staging_env.ports).to eq([111, 222, 333])
41
+ end
42
+ end
43
+
44
+ __END__
45
+
46
+ {
47
+ "production": {
48
+ "credentials": {
49
+ "user": "admin",
50
+ "password": "123",
51
+ "enabled": true
52
+ },
53
+ "api": "google.com",
54
+ "ports": [10001, 10002, 10003]
55
+ },
56
+ "test": {
57
+ "credentials": {
58
+ "user": "megaman",
59
+ "password": "atata123",
60
+ "enabled": false
61
+ },
62
+ "api": "yandex.ru",
63
+ "ports": [1, 2, 3]
64
+ },
65
+ "staging": {
66
+ "credentials": {
67
+ "user": "diablo",
68
+ "password": "testornot",
69
+ "enabled": true
70
+ },
71
+ "api": "battle.net",
72
+ "ports": [111, 222, 333]
73
+ }
74
+ }
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe '#expose_self => format: <unsupported>' do
4
+ specify 'fails on unsupported formats' do
5
+ expect do
6
+ Class.new(Qonfig::DataSet) do
7
+ expose_self env: :production, format: :atata
8
+ end
9
+ end.to raise_error(Qonfig::UnsupportedLoaderFormatError)
10
+ end
11
+
12
+ specify 'fails on empty format parameter' do
13
+ expect do
14
+ Class.new(Qonfig::DataSet) do
15
+ expose_self env: :production, format: ''
16
+ end
17
+ end.to raise_error(Qonfig::UnsupportedLoaderFormatError)
18
+ end
19
+
20
+ specify 'fails on incorrect format parameter' do
21
+ expect do
22
+ Class.new(Qonfig::DataSet) do
23
+ expose_self env: :production, format: Object.new
24
+ end
25
+ end.to raise_error(Qonfig::ArgumentError)
26
+ end
27
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe '#expose_self => format: :yaml' do
4
+ specify ':yaml-format support' do
5
+ class ExposeYamlEndDataConfig < Qonfig::DataSet
6
+ setting :staging_env do
7
+ expose_self format: :yaml, env: :staging
8
+ end
9
+
10
+ setting :prod_env do
11
+ expose_self format: :yml, env: :production # NOTE: yml is the same as yaml
12
+ end
13
+
14
+ setting :test_env do
15
+ expose_self format: :yaml, env: :test
16
+ end
17
+ end
18
+
19
+ config = ExposeYamlEndDataConfig.new
20
+
21
+ # NOTE: production env
22
+ expect(config.settings.prod_env.credentials.user).to eq('admin')
23
+ expect(config.settings.prod_env.credentials.password).to eq('123')
24
+ expect(config.settings.prod_env.credentials.enabled).to eq(true)
25
+ expect(config.settings.prod_env.api).to eq('google.com')
26
+ expect(config.settings.prod_env.ports).to eq([10001, 10002, 10003])
27
+
28
+ # NOTE: test env
29
+ expect(config.settings.test_env.credentials.user).to eq('megaman')
30
+ expect(config.settings.test_env.credentials.password).to eq('atata123')
31
+ expect(config.settings.test_env.credentials.enabled).to eq(false)
32
+ expect(config.settings.test_env.api).to eq('yandex.ru')
33
+ expect(config.settings.test_env.ports).to eq([1, 2, 3])
34
+
35
+ # NOTE: staging env
36
+ expect(config.settings.staging_env.credentials.user).to eq('diablo')
37
+ expect(config.settings.staging_env.credentials.password).to eq('testornot')
38
+ expect(config.settings.staging_env.credentials.enabled).to eq(true)
39
+ expect(config.settings.staging_env.api).to eq('battle.net')
40
+ expect(config.settings.staging_env.ports).to eq([111, 222, 333])
41
+ end
42
+ end
43
+
44
+ __END__
45
+
46
+ production:
47
+ credentials:
48
+ user: admin
49
+ password: '123'
50
+ enabled: true
51
+ api: google.com
52
+ ports:
53
+ - 10001
54
+ - 10002
55
+ - 10003
56
+
57
+ test:
58
+ credentials:
59
+ user: megaman
60
+ password: atata123
61
+ enabled: false
62
+ api: yandex.ru
63
+ ports:
64
+ - 1
65
+ - 2
66
+ - 3
67
+
68
+ staging:
69
+ credentials:
70
+ user: diablo
71
+ password: testornot
72
+ enabled: true
73
+ api: battle.net
74
+ ports:
75
+ - 111
76
+ - 222
77
+ - 333
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Expose self (expose __END__)' do
4
+ specify 'defines config object by __END__ instructions and specific environment settings' do
5
+ class ExposeSelfConfig < Qonfig::DataSet
6
+ setting :test_env do
7
+ expose_self env: :test # NOTE: format: :yaml by default
8
+ end
9
+
10
+ setting :dev_env do
11
+ expose_self env: :development # NOTE: format: :yaml by default
12
+ end
13
+
14
+ setting :stage_env do
15
+ expose_self env: :staging # NOTE: format: :yaml by default
16
+ end
17
+
18
+ setting :prod_env do
19
+ expose_self env: :production # NOTE: format: :yaml by default
20
+ end
21
+ end
22
+
23
+ settings = ExposeSelfConfig.new.settings
24
+
25
+ # :test env key
26
+ expect(settings.test_env.api_mode_enabled).to eq(true)
27
+ expect(settings.test_env.db_driver).to eq('in_memory')
28
+ expect(settings.test_env.logging).to eq(false)
29
+ expect(settings.test_env.credentials).to eq({})
30
+
31
+ # :production env key
32
+ expect(settings.prod_env.api_mode_enabled).to eq(true)
33
+ expect(settings.prod_env.db_driver).to eq('rom')
34
+ expect(settings.prod_env.logging).to eq(true)
35
+ expect(settings.prod_env.credentials).to eq({})
36
+
37
+ # :development env key
38
+ expect(settings.dev_env.api_mode_enabled).to eq(true)
39
+ expect(settings.dev_env.db_driver).to eq('sequel')
40
+ expect(settings.dev_env.logging).to eq(false)
41
+ expect(settings.dev_env.credentials).to eq({})
42
+
43
+ # :staging env key
44
+ expect(settings.stage_env.api_mode_enabled).to eq(true)
45
+ expect(settings.stage_env.db_driver).to eq('active_record')
46
+ expect(settings.stage_env.logging).to eq(true)
47
+ expect(settings.stage_env.credentials).to eq({})
48
+ end
49
+
50
+ describe 'failures and inconsistent situations' do
51
+ describe 'definition level errors' do
52
+ specify 'fails when :env attribute has non-string / non-symbol / non-numeric value' do
53
+ expect do
54
+ Class.new(Qonfig::DataSet) do
55
+ expose_self env: Object.new
56
+ end
57
+ end.to raise_error(Qonfig::ArgumentError)
58
+ end
59
+
60
+ specify 'fails when :env is empty' do
61
+ expect do
62
+ Class.new(Qonfig::DataSet) do
63
+ expose_self env: ''
64
+ end
65
+ end.to raise_error(Qonfig::ArgumentError)
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ __END__
72
+
73
+ default: &default
74
+ api_mode_enabled: true
75
+ logging: true
76
+ db_driver: in_memory
77
+ throttle_requests: false
78
+ credentials: {}
79
+
80
+ development:
81
+ <<: *default
82
+ db_driver: sequel
83
+ logging: false
84
+
85
+ test:
86
+ <<: *default
87
+ logging: false
88
+
89
+ staging:
90
+ <<: *default
91
+ db_driver: active_record
92
+ throttle_requests: true
93
+
94
+ production:
95
+ <<: *default
96
+ db_driver: rom
97
+ throttle_requests: true
@@ -0,0 +1,263 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'Expose YAML file' do
4
+ specify 'defines config object by yaml instructions and specific environment settings' do
5
+ class ExposeYAMLConfig < Qonfig::DataSet
6
+ yaml_file_path = SpecSupport.fixture_path('expose_yaml', 'project.yml')
7
+
8
+ setting :file_name_based do
9
+ setting :test_env do
10
+ # spec/fixtures/expose_yaml/project.test.yml
11
+ expose_yaml yaml_file_path, via: :file_name, env: :test
12
+ end
13
+
14
+ setting :prod_env do
15
+ # spec/fixtures/expose_yaml/project.production.yml
16
+ expose_yaml yaml_file_path, via: :file_name, env: :production
17
+ end
18
+
19
+ setting :stage_env do
20
+ # spec/fixtures/expose_yaml/project.staging.yml
21
+ expose_yaml yaml_file_path, via: :file_name, env: :staging
22
+ end
23
+
24
+ setting :dev_env do
25
+ # spec/fixtures/expose_yaml/project.development.yml
26
+ expose_yaml yaml_file_path, via: :file_name, env: :development
27
+ end
28
+ end
29
+
30
+ setting :env_based do
31
+ setting :test_env do
32
+ # spec/fixtures/expose_yaml/project.yml
33
+ expose_yaml yaml_file_path, via: :env_key, env: :test
34
+ end
35
+
36
+ setting :prod_env do
37
+ # spec/fixtures/expose_yaml/project.yml
38
+ expose_yaml yaml_file_path, via: :env_key, env: :production
39
+ end
40
+
41
+ setting :stage_env do
42
+ # spec/fixtures/expose_yaml/project.yml
43
+ expose_yaml yaml_file_path, via: :env_key, env: :staging
44
+ end
45
+
46
+ setting :dev_env do
47
+ # spec/fixtures/expose_yaml/project.yml
48
+ expose_yaml yaml_file_path, via: :env_key, env: :development
49
+ end
50
+ end
51
+ end
52
+
53
+ settings = ExposeYAMLConfig.new.settings
54
+
55
+ # NOTE: file-name based expose
56
+ # spec/fixtures/expose_yaml/project.test.yml
57
+ expect(settings.file_name_based.test_env.api_mode_enabled).to eq(false)
58
+ expect(settings.file_name_based.test_env.db_driver).to eq('in_memory')
59
+ expect(settings.file_name_based.test_env.logging).to eq(false)
60
+ expect(settings.file_name_based.test_env.credentials).to eq({})
61
+ # spec/fixtures/expose_yaml/project.production.yml
62
+ expect(settings.file_name_based.prod_env.api_mode_enabled).to eq(true)
63
+ expect(settings.file_name_based.prod_env.db_driver).to eq('rom')
64
+ expect(settings.file_name_based.prod_env.logging).to eq(true)
65
+ expect(settings.file_name_based.prod_env.credentials).to eq({})
66
+ # spec/fixtures/expose_yaml/project.development.yml
67
+ expect(settings.file_name_based.dev_env.api_mode_enabled).to eq(true)
68
+ expect(settings.file_name_based.dev_env.db_driver).to eq('sequel')
69
+ expect(settings.file_name_based.dev_env.logging).to eq(false)
70
+ expect(settings.file_name_based.dev_env.credentials).to eq({})
71
+ # spec/fixtures/expose_yaml/project.staging.yml
72
+ expect(settings.file_name_based.stage_env.api_mode_enabled).to eq(true)
73
+ expect(settings.file_name_based.stage_env.db_driver).to eq('active_record')
74
+ expect(settings.file_name_based.stage_env.logging).to eq(true)
75
+ expect(settings.file_name_based.stage_env.credentials).to eq({})
76
+
77
+ # NOTE: environment based expose
78
+ # spec/fixtures/expose_yaml/project.yml (key: 'test')
79
+ expect(settings.env_based.test_env.api_mode_enabled).to eq(true)
80
+ expect(settings.env_based.test_env.db_driver).to eq('in_memory')
81
+ expect(settings.env_based.test_env.logging).to eq(false)
82
+ expect(settings.env_based.test_env.throttle_requests).to eq(false)
83
+ expect(settings.env_based.test_env.credentials).to eq({})
84
+ # spec/fixtures/expose_yaml/project.yml (key: 'production')
85
+ expect(settings.env_based.prod_env.api_mode_enabled).to eq(true)
86
+ expect(settings.env_based.prod_env.db_driver).to eq('rom')
87
+ expect(settings.env_based.prod_env.logging).to eq(true)
88
+ expect(settings.env_based.prod_env.throttle_requests).to eq(true)
89
+ expect(settings.env_based.prod_env.credentials).to eq({})
90
+ # spec/fixtures/expose_yaml/project.yml (key: 'development')
91
+ expect(settings.env_based.dev_env.api_mode_enabled).to eq(true)
92
+ expect(settings.env_based.dev_env.db_driver).to eq('sequel')
93
+ expect(settings.env_based.dev_env.logging).to eq(false)
94
+ expect(settings.env_based.dev_env.throttle_requests).to eq(false)
95
+ expect(settings.env_based.dev_env.credentials).to eq({})
96
+ # spec/fixtures/expose_yaml/project.yml (key: 'staging')
97
+ expect(settings.env_based.stage_env.api_mode_enabled).to eq(true)
98
+ expect(settings.env_based.stage_env.db_driver).to eq('active_record')
99
+ expect(settings.env_based.stage_env.logging).to eq(true)
100
+ expect(settings.env_based.stage_env.throttle_requests).to eq(true)
101
+ expect(settings.env_based.stage_env.credentials).to eq({})
102
+ end
103
+
104
+ specify 'support for Pathname in file path' do
105
+ class PathnameExposeYamlCheck < Qonfig::DataSet
106
+ expose_yaml(
107
+ Pathname.new(SpecSupport.fixture_path('expose_yaml', 'project.yml')),
108
+ via: :env_key, env: :development
109
+ )
110
+ end
111
+
112
+ config = PathnameExposeYamlCheck.new
113
+
114
+ expect(config.settings.api_mode_enabled).to eq(true)
115
+ expect(config.settings.logging).to eq(false)
116
+ expect(config.settings.db_driver).to eq('sequel')
117
+ expect(config.settings.throttle_requests).to eq(false)
118
+ expect(config.settings.credentials).to eq({})
119
+ end
120
+
121
+ describe 'failures and inconsistent situations' do
122
+ describe 'definition level errors' do
123
+ specify 'fails when :env attribute has non-string / non-symbol / non-numeric value' do
124
+ expect do
125
+ Class.new(Qonfig::DataSet) do
126
+ expose_yaml SpecSupport.fixture_path(
127
+ 'expose_yaml', 'project.yml'
128
+ ), via: :env_key, env: Object.new
129
+ end
130
+ end.to raise_error(Qonfig::ArgumentError)
131
+ end
132
+
133
+ specify 'fails when :env is empty' do
134
+ expect do
135
+ Class.new(Qonfig::DataSet) do
136
+ expose_yaml SpecSupport.fixture_path(
137
+ 'expose_yaml', 'project.yml'
138
+ ), via: :env_key, env: ''
139
+ end
140
+ end.to raise_error(Qonfig::ArgumentError)
141
+ end
142
+
143
+ specify 'fails when provided :via is not supported' do
144
+ expect do
145
+ Class.new(Qonfig::DataSet) do
146
+ expose_yaml SpecSupport.fixture_path(
147
+ 'expose_yaml', 'project.yml'
148
+ ), via: :auto, env: :production
149
+ end
150
+ end.to raise_error(Qonfig::ArgumentError)
151
+ end
152
+ end
153
+
154
+ describe 'initialization level errors' do
155
+ specify 'fails when env-based settings is represented as a non-hash-like data' do
156
+ # NOTE:
157
+ # - file: spec/fixtures/expose_yaml/incompatible_structure.yml
158
+ # - :staging environment key has incorrect value (scalar)
159
+ # - :test environment key has correct value (hash)
160
+
161
+ class IncompatibleEnvBasedYAMLConfig < Qonfig::DataSet
162
+ expose_yaml SpecSupport.fixture_path(
163
+ 'expose_yaml', 'incompatible_structure.yml'
164
+ ), via: :env_key, env: :staging
165
+ end
166
+
167
+ expect do
168
+ IncompatibleEnvBasedYAMLConfig.new
169
+ end.to raise_error(Qonfig::IncompatibleYAMLStructureError)
170
+
171
+ class CompatibleEnvBasedYAMLConfig < Qonfig::DataSet
172
+ expose_yaml SpecSupport.fixture_path(
173
+ 'expose_yaml', 'incompatible_structure.yml'
174
+ ), via: :env_key, env: :test
175
+ end
176
+
177
+ expect { CompatibleEnvBasedYAMLConfig.new }.not_to raise_error
178
+ end
179
+
180
+ describe 'strict mode' do
181
+ specify(
182
+ 'disabled (non-strict): ' \
183
+ 'file existence requirement + yaml-env-key existence requirement'
184
+ ) do
185
+ # NOTE: file does not exist + env key does not exist in yml file
186
+ class NoFileNonStrictExposeYAMLConfig < Qonfig::DataSet
187
+ setting :non_strict_by_file do
188
+ expose_yaml SpecSupport.fixture_path(
189
+ 'expose_yaml', 'nonexistent.yml'
190
+ ), strict: false, via: :file_name, env: :development
191
+ end
192
+
193
+ setting :non_strict_by_env do
194
+ expose_yaml SpecSupport.fixture_path(
195
+ 'expose_yaml', 'nonexistent.yml'
196
+ ), strict: false, via: :env_key, env: :development
197
+ end
198
+ end
199
+
200
+ expect(NoFileNonStrictExposeYAMLConfig.new.to_h).to match(
201
+ 'non_strict_by_file' => {},
202
+ 'non_strict_by_env' => {}
203
+ )
204
+
205
+ # NOTE: file is exist + env key does not exist in yml file
206
+ class NoEnvKeyNonStrictExposeYAMLConfig < Qonfig::DataSet
207
+ setting :non_strict_by_file do
208
+ expose_yaml SpecSupport.fixture_path(
209
+ 'expose_yaml', 'project.yml'
210
+ ), strict: false, via: :file_name, env: :nonexistent
211
+ end
212
+
213
+ setting :non_strict_by_env do
214
+ expose_yaml SpecSupport.fixture_path(
215
+ 'expose_yaml', 'project.yml'
216
+ ), strict: false, via: :env_key, env: :nonexistent
217
+ end
218
+ end
219
+
220
+ expect(NoEnvKeyNonStrictExposeYAMLConfig.new.to_h).to match(
221
+ 'non_strict_by_file' => {},
222
+ 'non_strict_by_env' => {}
223
+ )
224
+ end
225
+
226
+ specify(
227
+ 'enabled (strict, by default): ' \
228
+ 'file existence requirement + yaml-env-key existence requirement'
229
+ ) do
230
+ # NOTE: file does not exist
231
+ class StrictFileViaFileNameYAMLConfig < Qonfig::DataSet
232
+ expose_yaml SpecSupport.fixture_path(
233
+ 'expose_yaml', 'nonexistent.yml'
234
+ ), via: :file_name, env: :production
235
+ end
236
+
237
+ # NOTE: file does not exist
238
+ class StrictFileViaEnvKeyYAMLConfig < Qonfig::DataSet
239
+ expose_yaml SpecSupport.fixture_path(
240
+ 'expose_yaml', 'nonexistent.yml'
241
+ ), via: :env_key, env: :production
242
+ end
243
+
244
+ # NOTE: file does not exist
245
+ expect { StrictFileViaFileNameYAMLConfig.new }.to raise_error(Qonfig::FileNotFoundError)
246
+ expect { StrictFileViaEnvKeyYAMLConfig.new }.to raise_error(Qonfig::FileNotFoundError)
247
+
248
+ # NOTE:
249
+ # - file exists but env key does not exist
250
+ # - file: spec/fixtures/expose_yaml/project.yml
251
+ class NonExistentEnvKeyYAMLConfig < Qonfig::DataSet
252
+ expose_yaml SpecSupport.fixture_path(
253
+ 'expose_yaml', 'project.yml'
254
+ ), via: :env_key, env: :nonexistent
255
+ end
256
+
257
+ # NOTE: env key does not exist
258
+ expect { NonExistentEnvKeyYAMLConfig.new }.to raise_error(Qonfig::ExposeError)
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end