config_files 0.1.6 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +94 -0
  3. data/.gitignore +2 -3
  4. data/.rubocop.yml +81 -0
  5. data/CHANGELOG.md +154 -0
  6. data/Gemfile +12 -1
  7. data/MULTI_RUBY_SETUP.md +158 -0
  8. data/README.md +246 -23
  9. data/Rakefile +26 -3
  10. data/TESTING.md +226 -0
  11. data/config_files.gemspec +12 -9
  12. data/docker/Dockerfile.test +32 -0
  13. data/lib/config_files/file_factory.rb +7 -3
  14. data/lib/config_files/loader_factory.rb +20 -11
  15. data/lib/config_files/loaders/base_parser.rb +133 -0
  16. data/lib/config_files/loaders/conf.rb +61 -0
  17. data/lib/config_files/loaders/default.rb +3 -1
  18. data/lib/config_files/loaders/ini.rb +48 -0
  19. data/lib/config_files/loaders/json.rb +3 -1
  20. data/lib/config_files/loaders/xml.rb +67 -0
  21. data/lib/config_files/loaders/yaml.rb +2 -0
  22. data/lib/config_files/loaders.rb +6 -1
  23. data/lib/config_files/version.rb +3 -1
  24. data/lib/config_files.rb +34 -18
  25. data/lib/meta.rb +3 -1
  26. data/scripts/install_rubies_asdf.sh +187 -0
  27. data/scripts/test_docker.sh +91 -0
  28. data/scripts/test_multiple_rubies.sh +290 -0
  29. data/test/comprehensive_multi_directory_test.rb +168 -0
  30. data/test/config/dummy.json +10 -0
  31. data/test/config/dummy.yml +6 -0
  32. data/test/config_files_test.rb +10 -8
  33. data/test/etc/dummy.conf +14 -2
  34. data/test/etc/dummy.ini +12 -0
  35. data/test/etc/dummy.xml +13 -0
  36. data/test/etc/dummy.yml +2 -2
  37. data/test/loader_factory_test.rb +10 -10
  38. data/test/loaders_test.rb +362 -0
  39. data/test/local/dummy.json +10 -0
  40. data/test/local/dummy.yml +6 -0
  41. data/test/mixed_format_test.rb +152 -0
  42. data/test/multi_directory_test.rb +126 -0
  43. data/test/test_helper.rb +3 -0
  44. metadata +49 -26
  45. data/Gemfile.lock +0 -34
@@ -1,40 +1,40 @@
1
- $:.push(File.join(File.dirname(__FILE__), '..', 'lib'))
1
+ $LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'minitest/autorun'
3
3
  require 'config_files'
4
4
  class LoaderFactoryDummy
5
5
  class << self
6
- def call(file_name, options={})
6
+ def call(_file_name, _options = {})
7
7
  nil
8
8
  end
9
9
  end
10
10
  end
11
11
 
12
- class LoaderFactoryTest < MiniTest::Test
12
+ class LoaderFactoryTest < Minitest::Test
13
13
  def file_locations
14
14
  File.join(__dir__, 'etc')
15
15
  end
16
16
 
17
17
  def test_detect_yaml_file_type
18
- assert_equal(::ConfigFiles::Loaders::Yaml, ::ConfigFiles::LoaderFactory.(File.join(file_locations,'dummy.yml')))
18
+ assert_equal(::ConfigFiles::Loaders::Yaml, ::ConfigFiles::LoaderFactory.call(File.join(file_locations, 'dummy.yml')))
19
19
  end
20
20
 
21
21
  def test_detect_json_file_type
22
- assert_equal(::ConfigFiles::Loaders::Json, ::ConfigFiles::LoaderFactory.(File.join(file_locations,'dummy.json')))
22
+ assert_equal(::ConfigFiles::Loaders::Json, ::ConfigFiles::LoaderFactory.call(File.join(file_locations, 'dummy.json')))
23
23
  end
24
24
 
25
25
  def test_detect_unknown_file_type
26
- assert_nil(::ConfigFiles::LoaderFactory.(File.join(file_locations,'dummy.wibble'), default_loader: nil))
26
+ assert_nil(::ConfigFiles::LoaderFactory.call(File.join(file_locations, 'dummy.wibble'), default_loader: nil))
27
27
  end
28
28
 
29
29
  def test_allow_addition_of_file_types_does_not_break_existing
30
- assert_equal(::ConfigFiles::Loaders::Yaml, ::ConfigFiles::LoaderFactory.(File.join(file_locations,'dummy.yml'), loaders: {LoaderFactoryDummy=>['wibble']}))
30
+ assert_equal(::ConfigFiles::Loaders::Yaml, ::ConfigFiles::LoaderFactory.call(File.join(file_locations, 'dummy.yml'), loaders: { LoaderFactoryDummy => ['wibble'] }))
31
31
  end
32
32
 
33
33
  def test_allow_addition_of_file_types_breaks_existing_if_specified
34
- assert_nil(::ConfigFiles::LoaderFactory.(File.join(file_locations,'dummy.yml'), loaders: {LoaderFactoryDummy=>['wibble']}, include_default: false, default_loader: nil))
34
+ assert_nil(::ConfigFiles::LoaderFactory.call(File.join(file_locations, 'dummy.yml'), loaders: { LoaderFactoryDummy => ['wibble'] }, include_default: false, default_loader: nil))
35
35
  end
36
36
 
37
37
  def test_addition_of_new_loaders
38
- assert_equal(LoaderFactoryDummy, ::ConfigFiles::LoaderFactory.(File.join(file_locations,'dummy.wibble'), loaders: {LoaderFactoryDummy=>['wibble']}, include_default: false))
38
+ assert_equal(LoaderFactoryDummy, ::ConfigFiles::LoaderFactory.call(File.join(file_locations, 'dummy.wibble'), loaders: { LoaderFactoryDummy => ['wibble'] }, include_default: false))
39
39
  end
40
- end
40
+ end
@@ -0,0 +1,362 @@
1
+ require 'test_helper'
2
+ require 'tempfile'
3
+
4
+ class LoadersTest < Minitest::Test
5
+ def setup
6
+ @temp_files = []
7
+ end
8
+
9
+ def teardown
10
+ @temp_files.each(&:unlink)
11
+ end
12
+
13
+ def create_temp_file(content, extension = '.tmp')
14
+ file = Tempfile.new(['test', extension])
15
+ file.write(content)
16
+ file.close
17
+ @temp_files << file
18
+ file.path
19
+ end
20
+
21
+ # CONF Parser Tests
22
+ def test_conf_parser_basic_key_value_pairs
23
+ content = <<~CONF
24
+ key1=value1
25
+ key2: value2
26
+ key3 value3
27
+ CONF
28
+
29
+ file_path = create_temp_file(content, '.conf')
30
+ result = ConfigFiles::Loaders::Conf.call(file_path)
31
+
32
+ assert_equal 'value1', result['key1']
33
+ assert_equal 'value2', result['key2']
34
+ assert_equal 'value3', result['key3']
35
+ end
36
+
37
+ def test_conf_parser_sections
38
+ content = <<~CONF
39
+ global_key=global_value
40
+
41
+ [section1]
42
+ key1=value1
43
+ key2=value2
44
+
45
+ [section2]
46
+ key3=value3
47
+ CONF
48
+
49
+ file_path = create_temp_file(content, '.conf')
50
+ result = ConfigFiles::Loaders::Conf.call(file_path)
51
+
52
+ assert_equal 'global_value', result['global_key']
53
+ assert_equal 'value1', result['section1']['key1']
54
+ assert_equal 'value2', result['section1']['key2']
55
+ assert_equal 'value3', result['section2']['key3']
56
+ end
57
+
58
+ def test_conf_parser_nested_keys
59
+ content = <<~CONF
60
+ server.host=localhost
61
+ server.port=8080
62
+ database.connection.host=db.example.com
63
+
64
+ [app]
65
+ cache.redis.host=redis.example.com
66
+ cache.redis.port=6379
67
+ CONF
68
+
69
+ file_path = create_temp_file(content, '.conf')
70
+ result = ConfigFiles::Loaders::Conf.call(file_path)
71
+
72
+ assert_equal 'localhost', result['server']['host']
73
+ assert_equal 8080, result['server']['port']
74
+ assert_equal 'db.example.com', result['database']['connection']['host']
75
+ assert_equal 'redis.example.com', result['app']['cache']['redis']['host']
76
+ assert_equal 6379, result['app']['cache']['redis']['port']
77
+ end
78
+
79
+ def test_conf_parser_value_types
80
+ content = <<~CONF
81
+ string_value=hello world
82
+ quoted_string="quoted value"
83
+ single_quoted='single quoted'
84
+ integer_value=42
85
+ float_value=3.14
86
+ boolean_true=true
87
+ boolean_false=false
88
+ boolean_yes=yes
89
+ boolean_no=no
90
+ boolean_on=on
91
+ boolean_off=off
92
+ boolean_1=1
93
+ boolean_0=0
94
+ CONF
95
+
96
+ file_path = create_temp_file(content, '.conf')
97
+ result = ConfigFiles::Loaders::Conf.call(file_path)
98
+
99
+ assert_equal 'hello world', result['string_value']
100
+ assert_equal 'quoted value', result['quoted_string']
101
+ assert_equal 'single quoted', result['single_quoted']
102
+ assert_equal 42, result['integer_value']
103
+ assert_in_delta(3.14, result['float_value'])
104
+ assert result['boolean_true']
105
+ refute result['boolean_false']
106
+ assert result['boolean_yes']
107
+ refute result['boolean_no']
108
+ assert result['boolean_on']
109
+ refute result['boolean_off']
110
+ assert result['boolean_1']
111
+ refute result['boolean_0']
112
+ end
113
+
114
+ def test_conf_parser_comments_and_empty_lines
115
+ content = <<~CONF
116
+ # This is a comment
117
+ key1=value1
118
+
119
+ # Another comment
120
+ key2=value2
121
+
122
+ [section]
123
+ # Section comment
124
+ key3=value3
125
+ CONF
126
+
127
+ file_path = create_temp_file(content, '.conf')
128
+ result = ConfigFiles::Loaders::Conf.call(file_path)
129
+
130
+ assert_equal 'value1', result['key1']
131
+ assert_equal 'value2', result['key2']
132
+ assert_equal 'value3', result['section']['key3']
133
+ end
134
+
135
+ # INI Parser Tests
136
+ def test_ini_parser_basic_key_value_pairs
137
+ content = <<~INI
138
+ key1=value1
139
+ key2=value2
140
+ INI
141
+
142
+ file_path = create_temp_file(content, '.ini')
143
+ result = ConfigFiles::Loaders::Ini.call(file_path)
144
+
145
+ assert_equal 'value1', result['key1']
146
+ assert_equal 'value2', result['key2']
147
+ end
148
+
149
+ def test_ini_parser_sections
150
+ content = <<~INI
151
+ global_key=global_value
152
+
153
+ [section1]
154
+ key1=value1
155
+ key2=value2
156
+
157
+ [section2]
158
+ key3=value3
159
+ INI
160
+
161
+ file_path = create_temp_file(content, '.ini')
162
+ result = ConfigFiles::Loaders::Ini.call(file_path)
163
+
164
+ assert_equal 'global_value', result['global_key']
165
+ assert_equal 'value1', result['section1']['key1']
166
+ assert_equal 'value2', result['section1']['key2']
167
+ assert_equal 'value3', result['section2']['key3']
168
+ end
169
+
170
+ def test_ini_parser_value_types
171
+ content = <<~INI
172
+ string_value=hello world
173
+ quoted_string="quoted value"
174
+ single_quoted='single quoted'
175
+ integer_value=42
176
+ float_value=3.14
177
+ boolean_true=true
178
+ boolean_false=false
179
+ boolean_yes=yes
180
+ boolean_no=no
181
+ boolean_on=on
182
+ boolean_off=off
183
+ boolean_1=1
184
+ boolean_0=0
185
+ INI
186
+
187
+ file_path = create_temp_file(content, '.ini')
188
+ result = ConfigFiles::Loaders::Ini.call(file_path)
189
+
190
+ assert_equal 'hello world', result['string_value']
191
+ assert_equal 'quoted value', result['quoted_string']
192
+ assert_equal 'single quoted', result['single_quoted']
193
+ assert_equal 42, result['integer_value']
194
+ assert_in_delta(3.14, result['float_value'])
195
+ assert result['boolean_true']
196
+ refute result['boolean_false']
197
+ assert result['boolean_yes']
198
+ refute result['boolean_no']
199
+ assert result['boolean_on']
200
+ refute result['boolean_off']
201
+ assert result['boolean_1']
202
+ refute result['boolean_0']
203
+ end
204
+
205
+ def test_ini_parser_comments
206
+ content = <<~INI
207
+ # Hash comment
208
+ ; Semicolon comment
209
+ key1=value1
210
+
211
+ [section]
212
+ # Section comment
213
+ ; Another section comment
214
+ key2=value2
215
+ INI
216
+
217
+ file_path = create_temp_file(content, '.ini')
218
+ result = ConfigFiles::Loaders::Ini.call(file_path)
219
+
220
+ assert_equal 'value1', result['key1']
221
+ assert_equal 'value2', result['section']['key2']
222
+ end
223
+
224
+ # XML Parser Tests
225
+ def test_xml_parser_basic_structure
226
+ content = <<~XML
227
+ <?xml version="1.0" encoding="UTF-8"?>
228
+ <config>
229
+ <key1>value1</key1>
230
+ <key2>value2</key2>
231
+ </config>
232
+ XML
233
+
234
+ file_path = create_temp_file(content, '.xml')
235
+ result = ConfigFiles::Loaders::Xml.call(file_path)
236
+
237
+ assert_equal 'value1', result['key1']
238
+ assert_equal 'value2', result['key2']
239
+ end
240
+
241
+ def test_xml_parser_nested_elements
242
+ content = <<~XML
243
+ <?xml version="1.0" encoding="UTF-8"?>
244
+ <config>
245
+ <database>
246
+ <host>localhost</host>
247
+ <port>5432</port>
248
+ </database>
249
+ <app>
250
+ <name>Test App</name>
251
+ <debug>true</debug>
252
+ </app>
253
+ </config>
254
+ XML
255
+
256
+ file_path = create_temp_file(content, '.xml')
257
+ result = ConfigFiles::Loaders::Xml.call(file_path)
258
+
259
+ assert_equal 'localhost', result['database']['host']
260
+ assert_equal 5432, result['database']['port']
261
+ assert_equal 'Test App', result['app']['name']
262
+ assert result['app']['debug']
263
+ end
264
+
265
+ def test_xml_parser_attributes
266
+ content = <<~XML
267
+ <?xml version="1.0" encoding="UTF-8"?>
268
+ <config>
269
+ <app name="Test App" version="1.0">
270
+ <debug>false</debug>
271
+ </app>
272
+ </config>
273
+ XML
274
+
275
+ file_path = create_temp_file(content, '.xml')
276
+ result = ConfigFiles::Loaders::Xml.call(file_path)
277
+
278
+ assert_equal 'Test App', result['app']['@name']
279
+ assert_in_delta(1.0, result['app']['@version'])
280
+ refute result['app']['debug']
281
+ end
282
+
283
+ def test_xml_parser_multiple_elements_same_name
284
+ content = <<~XML
285
+ <?xml version="1.0" encoding="UTF-8"?>
286
+ <config>
287
+ <item>value1</item>
288
+ <item>value2</item>
289
+ <item>value3</item>
290
+ </config>
291
+ XML
292
+
293
+ file_path = create_temp_file(content, '.xml')
294
+ result = ConfigFiles::Loaders::Xml.call(file_path)
295
+
296
+ assert_kind_of Array, result['item']
297
+ assert_equal 3, result['item'].length
298
+ assert_equal 'value1', result['item'][0]
299
+ assert_equal 'value2', result['item'][1]
300
+ assert_equal 'value3', result['item'][2]
301
+ end
302
+
303
+ def test_xml_parser_value_types
304
+ content = <<~XML
305
+ <?xml version="1.0" encoding="UTF-8"?>
306
+ <config>
307
+ <string_value>hello world</string_value>
308
+ <integer_value>42</integer_value>
309
+ <float_value>3.14</float_value>
310
+ <boolean_true>true</boolean_true>
311
+ <boolean_false>false</boolean_false>
312
+ <empty_value></empty_value>
313
+ </config>
314
+ XML
315
+
316
+ file_path = create_temp_file(content, '.xml')
317
+ result = ConfigFiles::Loaders::Xml.call(file_path)
318
+
319
+ assert_equal 'hello world', result['string_value']
320
+ assert_equal 42, result['integer_value']
321
+ assert_in_delta(3.14, result['float_value'])
322
+ assert result['boolean_true']
323
+ refute result['boolean_false']
324
+ assert_nil result['empty_value']
325
+ end
326
+
327
+ # Test existing dummy files to ensure compatibility
328
+ def test_existing_dummy_files
329
+ conf_result = ConfigFiles::Loaders::Conf.call('test/etc/dummy.conf')
330
+ ini_result = ConfigFiles::Loaders::Ini.call('test/etc/dummy.ini')
331
+ xml_result = ConfigFiles::Loaders::Xml.call('test/etc/dummy.xml')
332
+
333
+ # CONF file assertions
334
+ assert_equal 'test2', conf_result['config_test']
335
+ assert_equal 'conf_file', conf_result['only_in_conf']
336
+ assert_equal 'myserver', conf_result['server']['name']
337
+ assert_equal 'nested_value', conf_result['nested']['config']['value']
338
+ assert_equal 'conf-db.example.com', conf_result['database']['host']
339
+ assert_equal 5433, conf_result['database']['port']
340
+ assert conf_result['database']['ssl']
341
+ assert_equal 'CONF App', conf_result['app']['name']
342
+ refute conf_result['app']['debug']
343
+
344
+ # INI file assertions
345
+ assert_equal 'ini_value', ini_result['global_setting']
346
+ assert_equal 'ini-db.example.com', ini_result['database']['host']
347
+ assert_equal 3306, ini_result['database']['port']
348
+ assert ini_result['database']['ssl']
349
+ assert_equal 'INI App', ini_result['app']['name']
350
+ refute ini_result['app']['debug']
351
+ assert_in_delta(2.0, ini_result['app']['version'])
352
+
353
+ # XML file assertions
354
+ assert_equal 'xml_value', xml_result['global_setting']
355
+ assert_equal 'xml-db.example.com', xml_result['database']['host']
356
+ assert_equal 5432, xml_result['database']['port']
357
+ assert xml_result['database']['ssl']
358
+ assert_equal 'XML App', xml_result['app']['@name']
359
+ refute xml_result['app']['debug']
360
+ assert_in_delta(3.0, xml_result['app']['version'])
361
+ end
362
+ end
@@ -0,0 +1,10 @@
1
+ {
2
+ "api": {
3
+ "endpoint": "https://localhost:3000",
4
+ "debug": true
5
+ },
6
+ "features": {
7
+ "feature_b": true,
8
+ "feature_c": true
9
+ }
10
+ }
@@ -0,0 +1,6 @@
1
+ config_test: local_override
2
+ database:
3
+ host: localhost
4
+ username: local_user
5
+ only_in_local: local_only
6
+ shared_key: from_local
@@ -0,0 +1,152 @@
1
+ $LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'minitest/autorun'
3
+ require 'config_files'
4
+ require 'fileutils'
5
+
6
+ class MixedFormatTest < Minitest::Test
7
+ def setup
8
+ # Create test directories and files with mixed formats
9
+ FileUtils.mkdir_p('test/format_test/dir1')
10
+ FileUtils.mkdir_p('test/format_test/dir2')
11
+ FileUtils.mkdir_p('test/format_test/dir3')
12
+
13
+ # dir1: YAML file
14
+ File.write('test/format_test/dir1/config.yml', <<~YAML)
15
+ database:
16
+ host: yaml-host
17
+ port: 5432
18
+ app:
19
+ name: yaml-app
20
+ debug: false
21
+ yaml_only: true
22
+ YAML
23
+
24
+ # dir2: JSON file
25
+ File.write('test/format_test/dir2/config.json', <<~JSON)
26
+ {
27
+ "database": {
28
+ "host": "json-host",
29
+ "username": "json-user"
30
+ },
31
+ "app": {
32
+ "name": "json-app",
33
+ "version": "1.0.0"
34
+ },
35
+ "json_only": true
36
+ }
37
+ JSON
38
+
39
+ # dir3: Both YAML and JSON files
40
+ File.write('test/format_test/dir3/config.yml', <<~YAML)
41
+ database:
42
+ host: final-yaml-host
43
+ password: secret
44
+ app:
45
+ debug: true
46
+ final_yaml: true
47
+ YAML
48
+
49
+ File.write('test/format_test/dir3/config.json', <<~JSON)
50
+ {
51
+ "database": {
52
+ "host": "final-json-host",
53
+ "timeout": 30
54
+ },
55
+ "app": {
56
+ "environment": "production"
57
+ },
58
+ "final_json": true
59
+ }
60
+ JSON
61
+ end
62
+
63
+ def teardown
64
+ FileUtils.rm_rf('test/format_test')
65
+ end
66
+
67
+ def test_mixed_yaml_and_json_across_directories
68
+ # Test class that uses mixed format directories
69
+ mixed_class = Class.new do
70
+ include ConfigFiles
71
+ config_directories etc: ['test/format_test/dir1', 'test/format_test/dir2', 'test/format_test/dir3']
72
+ static_config_files :config
73
+ end
74
+
75
+ config = mixed_class.config
76
+
77
+ # Test that values from all formats are present
78
+ assert config.key?(:yaml_only), "Should have YAML-only value from dir1"
79
+ assert config.key?(:json_only), "Should have JSON-only value from dir2"
80
+ assert config.key?(:final_yaml), "Should have YAML value from dir3"
81
+ assert config.key?(:final_json), "Should have JSON value from dir3"
82
+
83
+ # Test deep merging across formats with dir1 taking precedence
84
+ assert config[:database], "Should have database config"
85
+ assert_equal 'yaml-host', config[:database][:host], "Host should be from dir1 (highest priority)"
86
+ assert_equal 5432, config[:database][:port], "Port should come from YAML in dir1"
87
+ assert_equal 'json-user', config[:database][:username], "Username should come from JSON in dir2"
88
+ assert_equal 'secret', config[:database][:password], "Password should come from YAML in dir3"
89
+ assert_equal 30, config[:database][:timeout], "Timeout should come from JSON in dir3"
90
+
91
+ # Test app config merging
92
+ assert config[:app], "Should have app config"
93
+ assert_equal 'yaml-app', config[:app][:name], "Name should be from dir1 (highest priority)"
94
+ refute config[:app][:debug], "Debug should be from dir1 (highest priority)"
95
+ assert_equal '1.0.0', config[:app][:version], "Version should come from JSON in dir2"
96
+ assert_equal 'production', config[:app][:environment], "Environment should come from JSON in dir3"
97
+ end
98
+
99
+ def test_multiple_files_same_directory_same_format
100
+ # Test when a directory has multiple files of the same format
101
+ FileUtils.mkdir_p('test/format_test/multi')
102
+
103
+ File.write('test/format_test/multi/config.yml', <<~YAML)
104
+ from_yml: true
105
+ shared: yml_value
106
+ YAML
107
+
108
+ File.write('test/format_test/multi/config.json', <<~JSON)
109
+ {
110
+ "from_json": true,
111
+ "shared": "json_value"
112
+ }
113
+ JSON
114
+
115
+ multi_class = Class.new do
116
+ include ConfigFiles
117
+ config_directories etc: ['test/format_test/multi']
118
+ static_config_files :config
119
+ end
120
+
121
+ config = multi_class.config
122
+
123
+ # Both formats should be loaded and merged
124
+ assert config.key?(:from_yml), "Should have YAML values"
125
+ assert config.key?(:from_json), "Should have JSON values"
126
+
127
+ # YAML should override JSON (alphabetical order: config.yml comes after config.json)
128
+ assert_equal 'yml_value', config[:shared], "YAML should override JSON for same key"
129
+ end
130
+
131
+ def test_file_processing_order_within_directory
132
+ # Test that files are processed in a predictable order within each directory
133
+ FileUtils.mkdir_p('test/format_test/order')
134
+
135
+ # Create files that will be processed in alphabetical order
136
+ File.write('test/format_test/order/config.json', '{"order": "json", "source": "json"}')
137
+ File.write('test/format_test/order/config.yml', "order: yaml\nsource: yaml")
138
+ File.write('test/format_test/order/config.conf', ":order: conf\n:source: conf")
139
+
140
+ order_class = Class.new do
141
+ include ConfigFiles
142
+ config_directories etc: ['test/format_test/order']
143
+ static_config_files :config
144
+ end
145
+
146
+ config = order_class.config
147
+
148
+ # The last file alphabetically should win (yml comes after json and conf)
149
+ assert_equal 'yaml', config[:order]
150
+ assert_equal 'yaml', config[:source]
151
+ end
152
+ end