dry-configurable 0.1.7 → 0.7.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.
@@ -1,108 +1,391 @@
1
1
  RSpec.shared_examples 'a configurable class' do
2
2
  describe Dry::Configurable do
3
3
  describe 'settings' do
4
- context 'without default value' do
5
- before do
6
- klass.setting :dsn
4
+ context 'without processor option' do
5
+ context 'without default value' do
6
+ before do
7
+ klass.setting :dsn
8
+ end
9
+
10
+ it 'returns nil' do
11
+ expect(klass.config.dsn).to be(nil)
12
+ end
7
13
  end
8
14
 
9
- it 'returns nil' do
10
- expect(klass.config.dsn).to be(nil)
15
+ context 'with default value' do
16
+ context 'with a nil default value' do
17
+ before do
18
+ klass.setting :dsn, nil
19
+ end
20
+
21
+ it 'returns the default value' do
22
+ expect(klass.config.dsn).to be(nil)
23
+ end
24
+ end
25
+
26
+ context 'with a false default value' do
27
+ before do
28
+ klass.setting :dsn, false
29
+ end
30
+
31
+ it 'returns the default value' do
32
+ expect(klass.config.dsn).to be(false)
33
+ end
34
+ end
35
+
36
+ context 'with a string default value' do
37
+ before do
38
+ klass.setting :dsn, 'sqlite:memory'
39
+ end
40
+
41
+ it 'returns the default value' do
42
+ expect(klass.config.dsn).to eq('sqlite:memory')
43
+ end
44
+ end
45
+
46
+ context 'with a hash default value' do
47
+ before do
48
+ klass.setting :db_config, {
49
+ user: 'root',
50
+ password: ''
51
+ }
52
+ end
53
+
54
+ it 'returns the default value' do
55
+ expect(klass.config.db_config).to eq(
56
+ user: 'root',
57
+ password: ''
58
+ )
59
+ end
60
+ end
11
61
  end
12
- end
13
62
 
14
- context 'with default value' do
15
- before do
16
- klass.setting :dsn, 'sqlite:memory'
63
+ context 'reader option' do
64
+ context 'without passing option' do
65
+ before do
66
+ klass.setting :dsn
67
+ end
68
+
69
+ before do
70
+ klass.configure do |config|
71
+ config.dsn = 'jdbc:sqlite:memory'
72
+ end
73
+ end
74
+
75
+ it 'will not create a getter method' do
76
+ expect(klass.respond_to?(:dsn)).to be_falsey
77
+ end
78
+ end
79
+
80
+ context 'with hash as value ' do
81
+ before do
82
+ klass.setting :dsn, { foo: 'bar' }, reader: true
83
+ end
84
+
85
+ it 'will create a getter method' do
86
+ expect(klass.dsn).to eq(foo: 'bar')
87
+ expect(klass.respond_to?(:dsn)).to be_truthy
88
+ end
89
+ end
90
+
91
+ context 'with option set to true' do
92
+ before do
93
+ klass.setting :dsn, 'testing', reader: true
94
+ end
95
+
96
+ it 'will create a getter method' do
97
+ expect(klass.dsn).to eq 'testing'
98
+ expect(klass.respond_to?(:dsn)).to be_truthy
99
+ end
100
+ end
101
+
102
+ context 'with nested configuration' do
103
+ before do
104
+ klass.setting :dsn, reader: true do
105
+ setting :pool, 5
106
+ end
107
+ end
108
+
109
+ it 'will create a nested getter method' do
110
+ expect(klass.dsn.pool).to eq 5
111
+ end
112
+ end
113
+
114
+ context 'with processor' do
115
+ context 'with default value' do
116
+ before do
117
+ klass.setting(:dsn, 'memory', reader: true) { |dsn| "sqlite:#{dsn}" }
118
+ end
119
+
120
+ it 'returns the default value' do
121
+ expect(klass.dsn).to eq('sqlite:memory')
122
+ end
123
+ end
124
+
125
+ context 'without default value' do
126
+ before do
127
+ klass.setting(:dsn, reader: true) { |dsn| "sqlite:#{dsn}" }
128
+ end
129
+
130
+ it 'returns the default value' do
131
+ expect(klass.dsn).to eq(nil)
132
+ end
133
+ end
134
+ end
17
135
  end
18
136
 
19
- it 'returns the default value' do
20
- expect(klass.config.dsn).to eq('sqlite:memory')
137
+ context 'nested configuration' do
138
+ before do
139
+ klass.setting :database do
140
+ setting :dsn, 'sqlite:memory'
141
+ end
142
+ end
143
+
144
+ it 'returns the default value' do
145
+ expect(klass.config.database.dsn).to eq('sqlite:memory')
146
+ end
21
147
  end
22
148
  end
23
149
 
24
- context 'nested configuration' do
25
- before do
26
- klass.setting :database do
27
- setting :dsn, 'sqlite:memory'
150
+ context 'with processor' do
151
+ context 'without default value' do
152
+ before do
153
+ klass.setting(:dsn) { |dsn| "sqlite:#{dsn}" }
154
+ end
155
+
156
+ it 'returns nil' do
157
+ expect(klass.config.dsn).to be(nil)
28
158
  end
29
159
  end
30
160
 
31
- it 'returns the default value' do
32
- expect(klass.config.database.dsn).to eq('sqlite:memory')
161
+ context 'with default value' do
162
+ before do
163
+ klass.setting(:dsn, 'memory') { |dsn| "sqlite:#{dsn}" }
164
+ end
165
+
166
+ it 'returns the default value' do
167
+ expect(klass.config.dsn).to eq('sqlite:memory')
168
+ end
169
+ end
170
+
171
+ context 'nested configuration' do
172
+ before do
173
+ klass.setting :database do
174
+ setting(:dsn, 'memory') { |dsn| "sqlite:#{dsn}" }
175
+ end
176
+ end
177
+
178
+ it 'returns the default value' do
179
+ expect(klass.config.database.dsn).to eq('sqlite:memory')
180
+ end
33
181
  end
34
182
  end
35
183
  end
36
184
 
37
185
  describe 'configuration' do
38
186
  context 'without nesting' do
39
- before do
40
- klass.setting :dsn, 'sqlite:memory'
41
- end
187
+ context 'without processor' do
188
+ before do
189
+ klass.setting :dsn, 'sqlite:memory'
190
+ end
42
191
 
43
- before do
44
- klass.configure do |config|
45
- config.dsn = 'jdbc:sqlite:memory'
192
+ before do
193
+ klass.configure do |config|
194
+ config.dsn = 'jdbc:sqlite:memory'
195
+ end
196
+ end
197
+
198
+ it 'updates the config value' do
199
+ expect(klass.config.dsn).to eq('jdbc:sqlite:memory')
46
200
  end
47
201
  end
48
202
 
49
- it 'updates the config value' do
50
- expect(klass.config.dsn).to eq('jdbc:sqlite:memory')
203
+ context 'with processor' do
204
+ before do
205
+ klass.setting(:dsn, 'sqlite') { |dsn| "#{dsn}:memory" }
206
+ end
207
+
208
+ before do
209
+ klass.configure do |config|
210
+ config.dsn = 'jdbc:sqlite'
211
+ end
212
+ end
213
+
214
+ it 'updates the config value' do
215
+ expect(klass.config.dsn).to eq('jdbc:sqlite:memory')
216
+ end
51
217
  end
52
218
  end
53
219
 
54
220
  context 'with nesting' do
55
- before do
56
- klass.setting :database do
57
- setting :dsn, 'sqlite:memory'
221
+ context 'without processor' do
222
+ before do
223
+ klass.setting :database do
224
+ setting :dsn, 'sqlite:memory'
225
+ end
226
+
227
+ klass.configure do |config|
228
+ config.database.dsn = 'jdbc:sqlite:memory'
229
+ end
58
230
  end
59
231
 
60
- klass.configure do |config|
61
- config.database.dsn = 'jdbc:sqlite:memory'
232
+ it 'updates the config value' do
233
+ expect(klass.config.database.dsn).to eq('jdbc:sqlite:memory')
62
234
  end
63
235
  end
64
236
 
65
- it 'updates the config value' do
66
- expect(klass.config.database.dsn).to eq('jdbc:sqlite:memory')
237
+ context 'with processor' do
238
+ before do
239
+ klass.setting :database do
240
+ setting(:dsn, 'sqlite') { |dsn| "#{dsn}:memory" }
241
+ end
242
+
243
+ klass.configure do |config|
244
+ config.database.dsn = 'jdbc:sqlite'
245
+ end
246
+ end
247
+
248
+ it 'updates the config value' do
249
+ expect(klass.config.database.dsn).to eq('jdbc:sqlite:memory')
250
+ end
67
251
  end
68
252
  end
69
253
 
70
- context 'when inherited' do
254
+ context 'when finalized' do
71
255
  before do
72
256
  klass.setting :dsn
73
257
  klass.configure do |config|
74
- config.dsn = 'jdbc:sqlite:memory'
258
+ config.dsn = 'jdbc:sqlite'
75
259
  end
260
+ klass.finalize!
76
261
  end
77
262
 
78
- subject!(:subclass) { Class.new(klass) }
263
+ it 'disallows modification' do
264
+ expect do
265
+ klass.configure do |config|
266
+ config.dsn = 'jdbc:sqlite'
267
+ end
268
+ end.to raise_error(Dry::Configurable::FrozenConfig, 'Cannot modify frozen config')
269
+ end
79
270
 
80
- it 'retains its configuration' do
81
- expect(subclass.config.dsn).to eq('jdbc:sqlite:memory')
271
+ it 'disallows direct modification on config' do
272
+ expect do
273
+ klass.config.dsn = 'jdbc:sqlite:memory'
274
+ end.to raise_error(Dry::Configurable::FrozenConfig, 'Cannot modify frozen config')
82
275
  end
276
+ end
83
277
 
84
- context 'when the inherited config is modified' do
278
+ context 'when inherited' do
279
+ context 'without processor' do
85
280
  before do
86
- subclass.configure do |config|
87
- config.dsn = 'jdbc:sqlite:file'
281
+ klass.setting :dsn
282
+ klass.configure do |config|
283
+ config.dsn = 'jdbc:sqlite:memory'
88
284
  end
89
285
  end
90
286
 
91
- it 'does not modify the original' do
92
- expect(klass.config.dsn).to eq('jdbc:sqlite:memory')
287
+ subject!(:subclass) { Class.new(klass) }
288
+
289
+ it 'retains its configuration' do
290
+ expect(subclass.config.dsn).to eq('jdbc:sqlite:memory')
291
+ end
292
+
293
+ context 'when the inherited config is modified' do
294
+ before do
295
+ subclass.configure do |config|
296
+ config.dsn = 'jdbc:sqlite:file'
297
+ end
298
+ end
299
+
300
+ it 'does not modify the original' do
301
+ expect(klass.config.dsn).to eq('jdbc:sqlite:memory')
302
+ expect(subclass.config.dsn).to eq('jdbc:sqlite:file')
303
+ end
304
+ end
305
+ end
306
+
307
+ context 'with processor' do
308
+ before do
309
+ klass.setting(:dsn) { |dsn| "#{dsn}:memory" }
310
+ klass.configure do |config|
311
+ config.dsn = 'jdbc:sqlite'
312
+ end
313
+ end
314
+
315
+ subject!(:subclass) { Class.new(klass) }
316
+
317
+ it 'retains its configuration' do
318
+ expect(subclass.config.dsn).to eq('jdbc:sqlite:memory')
319
+ end
320
+
321
+ context 'when the inherited config is modified' do
322
+ before do
323
+ subclass.configure do |config|
324
+ config.dsn = 'sqlite'
325
+ end
326
+ end
327
+
328
+ it 'does not modify the original' do
329
+ expect(klass.config.dsn).to eq('jdbc:sqlite:memory')
330
+ expect(subclass.config.dsn).to eq('sqlite:memory')
331
+ end
93
332
  end
94
333
  end
95
334
 
96
335
  context 'when the inherited settings are modified' do
97
336
  before do
337
+ klass.setting :dsn
98
338
  subclass.setting :db
339
+ klass.configure do |config|
340
+ config.dsn = 'jdbc:sqlite:memory'
341
+ end
99
342
  end
100
343
 
344
+ subject!(:subclass) { Class.new(klass) }
345
+
101
346
  it 'does not modify the original' do
102
- expect(klass._settings.keys).to_not include(:db)
347
+ expect(klass.settings).to_not include(:db)
103
348
  end
104
349
  end
105
350
  end
106
351
  end
352
+
353
+ context 'Test Interface' do
354
+ before { klass.enable_test_interface }
355
+
356
+ describe 'reset_config' do
357
+ before do
358
+ klass.setting :dsn, nil
359
+ klass.setting :pool do
360
+ setting :size, nil
361
+ end
362
+
363
+ klass.configure do |config|
364
+ config.dsn = 'sqlite:memory'
365
+ config.pool.size = 5
366
+ end
367
+
368
+ klass.reset_config
369
+ end
370
+
371
+ it 'resets configuration to default values' do
372
+ expect(klass.config.dsn).to be_nil
373
+ expect(klass.config.pool.size).to be_nil
374
+ end
375
+ end
376
+ end
377
+
378
+ context 'Try to set new value after config has been created' do
379
+ before do
380
+ klass.setting :dsn, 'sqlite:memory'
381
+ klass.config
382
+ end
383
+
384
+ it 'raise an exception' do
385
+ expect { klass.setting :pool, 5 }.to raise_error(
386
+ Dry::Configurable::AlreadyDefinedConfig
387
+ )
388
+ end
389
+ end
107
390
  end
108
391
  end
@@ -0,0 +1,114 @@
1
+ RSpec.describe Dry::Configurable::ArgumentParser do
2
+ let(:klass) { Dry::Configurable::ArgumentParser }
3
+
4
+ context 'with no args' do
5
+ let(:parsed) { klass.new([]) }
6
+
7
+ it 'return default values' do
8
+ expect(parsed.value).to eq nil
9
+ expect(parsed.options).to eq({})
10
+ end
11
+ end
12
+
13
+ context 'with value and options' do
14
+ let(:parsed) { klass.new([value, options]) }
15
+
16
+ context 'valid options' do
17
+ let(:value) { 'dry-rb' }
18
+ let(:options) do
19
+ { reader: true }
20
+ end
21
+
22
+ it 'returns correct value and options' do
23
+ expect(parsed.value).to eq 'dry-rb'
24
+ expect(parsed.options).to eq(reader: true)
25
+ end
26
+ end
27
+
28
+ context 'invalid options' do
29
+ let(:value) { 'dry-rb' }
30
+ let(:options) do
31
+ { writer: true }
32
+ end
33
+
34
+ it 'returns correct values and empty options' do
35
+ expect(parsed.value).to eq 'dry-rb'
36
+ expect(parsed.options).to eq({})
37
+ end
38
+ end
39
+
40
+ context 'values as hash' do
41
+ let(:value) do
42
+ { db: 'dry-rb' }
43
+ end
44
+ let(:options) do
45
+ { reader: true }
46
+ end
47
+
48
+ it 'returns correct values and empty options' do
49
+ expect(parsed.value).to eq(db: 'dry-rb')
50
+ expect(parsed.options).to eq(reader: true)
51
+ end
52
+ end
53
+
54
+ context 'values as array' do
55
+ let(:value) { [1, 2, 3] }
56
+ let(:options) do
57
+ { reader: true }
58
+ end
59
+
60
+ it 'returns correct values and empty options' do
61
+ expect(parsed.value).to eq([1, 2, 3])
62
+ expect(parsed.options).to eq(reader: true)
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'with value only' do
68
+ let(:parsed) { klass.new([value]) }
69
+ context 'valid options' do
70
+ let(:value) { 'dry-rb' }
71
+
72
+ it 'returns correct value and options' do
73
+ expect(parsed.value).to eq 'dry-rb'
74
+ expect(parsed.options).to eq({})
75
+ end
76
+ end
77
+
78
+ context 'with hash with non option key' do
79
+ let(:value) do
80
+ { writer: true }
81
+ end
82
+
83
+ it 'returns correct value and options' do
84
+ expect(parsed.value).to eq(writer: true)
85
+ expect(parsed.options).to eq({})
86
+ end
87
+ end
88
+
89
+ context 'with hash with option key' do
90
+ let(:value) do
91
+ { reader: true, writer: true }
92
+ end
93
+
94
+ it 'returns correct value and options' do
95
+ expect(parsed.value).to eq nil
96
+ expect(parsed.options).to eq(reader: true)
97
+ end
98
+ end
99
+ end
100
+
101
+ context 'with options only' do
102
+ let(:parsed) { klass.new([options]) }
103
+ context 'valid options' do
104
+ let(:options) do
105
+ { reader: true }
106
+ end
107
+
108
+ it 'returns correct value and options' do
109
+ expect(parsed.value).to eq nil
110
+ expect(parsed.options).to eq(reader: true)
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,55 @@
1
+ RSpec.describe Dry::Configurable::Config::Value do
2
+ let(:klass) { Dry::Configurable::Config::Value }
3
+ let(:config) { klass.new(name, value, processor) }
4
+ let(:name) { :db }
5
+ let(:value) { 'test' }
6
+ let(:processor) { ->(v) { v } }
7
+
8
+ describe '#initialize' do
9
+ it 'coerces string name to symbol' do
10
+ config = klass.new('db', value, processor)
11
+
12
+ expect(config.name).to eq(:db)
13
+ end
14
+ end
15
+
16
+ describe '#name' do
17
+ subject! { config.name }
18
+
19
+ it { is_expected.to eq(name) }
20
+ end
21
+
22
+ describe '#value' do
23
+ subject! { config.value }
24
+
25
+ context 'when value is not NONE' do
26
+ it { is_expected.to eq(value) }
27
+ end
28
+
29
+ context 'when value is NONE' do
30
+ let(:value) { klass::NONE }
31
+
32
+ it { is_expected.to be(nil) }
33
+ end
34
+ end
35
+
36
+ describe '#processor' do
37
+ subject! { config.processor }
38
+
39
+ it { is_expected.to eq(processor) }
40
+ end
41
+
42
+ describe '#none?' do
43
+ subject! { config.none? }
44
+
45
+ context 'when value is not NONE' do
46
+ it { is_expected.to be(false) }
47
+ end
48
+
49
+ context 'when value is NONE' do
50
+ let(:value) { klass::NONE }
51
+
52
+ it { is_expected.to be(true) }
53
+ end
54
+ end
55
+ end