envied 0.9.3 → 0.10.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,274 +0,0 @@
1
- RSpec.describe ENVied::Coercer do
2
- it { is_expected.to respond_to :coerce }
3
- it { is_expected.to respond_to :coerced? }
4
- it { is_expected.to respond_to :coercible? }
5
- it { is_expected.to respond_to :supported_types }
6
- it { is_expected.to respond_to :supported_type? }
7
-
8
- describe '.supported_types' do
9
- it 'returns a sorted set of supported types' do
10
- expect(described_class.supported_types).to eq %i(array boolean date float hash integer string symbol time uri)
11
- end
12
- end
13
-
14
- describe '.supported_type?' do
15
- it 'returns true for supported type' do
16
- %i(array boolean date float hash integer string symbol time uri).each do |type|
17
- expect(described_class.supported_type?(type)).to eq true
18
- end
19
- end
20
-
21
- it 'returns false for unsupported type' do
22
- expect(described_class.supported_type?(:fixnum)).to eq false
23
- end
24
- end
25
-
26
- describe '#supported_types' do
27
- it 'calls class method implementation' do
28
- expect(described_class).to receive(:supported_types).and_call_original
29
- described_class.new.supported_types
30
- end
31
- end
32
-
33
- describe '#supported_type?' do
34
- it 'calls class method implementation' do
35
- expect(described_class).to receive(:supported_type?).with(:string).and_call_original
36
- described_class.new.supported_type?(:string)
37
- end
38
- end
39
-
40
- describe '#coerced?' do
41
- let(:coercer) { described_class.new }
42
-
43
- it 'returns true if value has been coerced (not a string)' do
44
- expect(coercer.coerced?(1)).to eq true
45
- end
46
-
47
- it 'returns false if value is not a string' do
48
- expect(coercer.coerced?('1')).to eq false
49
- end
50
- end
51
-
52
- describe '#coercible?' do
53
- let(:coercer) { described_class.new }
54
-
55
- it 'returns false for unsupported type' do
56
- expect(coercer.coercible?('value', :invalid_type)).to eq false
57
- end
58
-
59
- it 'returns false for a failed coercion' do
60
- expect(coercer.coercible?('value', :boolean)).to eq false
61
- end
62
-
63
- it 'returns true for a coercible value' do
64
- expect(coercer.coercible?('value', :string)).to eq true
65
- end
66
- end
67
-
68
- describe '#coerce' do
69
- let(:coercer){ described_class.new }
70
-
71
- def coerce(str, type)
72
- coercer.coerce(str, type)
73
- end
74
-
75
- it 'fails with an invalid type' do
76
- expect { coerce('', :fixnum) }.to raise_error(ArgumentError, "The type `:fixnum` is not supported.")
77
- end
78
-
79
- describe 'to string' do
80
- it 'returns the input untouched' do
81
- expect(coerce('1', :string)).to eq '1'
82
- expect(coerce(' 1', :string)).to eq ' 1'
83
- end
84
-
85
- it 'fails when the value does not respond to #to_str' do
86
- value = Object.new
87
- expect { coerce(value, :string) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
88
- end
89
- end
90
-
91
- describe 'to integer' do
92
- {
93
- '1' => 1,
94
- '+1' => 1,
95
- '-1' => -1,
96
- '10' => 10,
97
- '100_00' => 100_00,
98
- '1_000_00' => 1_000_00
99
- }.each do |value, integer|
100
- it "converts #{value.inspect} to an integer" do
101
- expect(coerce(value, :integer)).to be_kind_of(Integer)
102
- expect(coerce(value, :integer)).to eq integer
103
- end
104
- end
105
-
106
- it 'fails with an invalid string' do
107
- expect { coerce('non-integer', :integer) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
108
- end
109
-
110
- it 'fails with a float' do
111
- expect { coerce('1.23', :integer) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
112
- end
113
- end
114
-
115
- describe 'to float' do
116
- {
117
- '1' => 1.0,
118
- '+1' => 1.0,
119
- '-1' => -1.0,
120
- '1_000.0' => 1_000.0,
121
- '10_000.23' => 10_000.23,
122
- '1_000_000.0' => 1_000_000.0,
123
- '1.0' => 1.0,
124
- '1.234' => 1.234,
125
- '1.0e+1' => 10.0,
126
- '1.0e-1' => 0.1,
127
- '1.0E+1' => 10.0,
128
- '1.0E-1' => 0.1,
129
- '+1.0' => 1.0,
130
- '+1.0e+1' => 10.0,
131
- '+1.0e-1' => 0.1,
132
- '+1.0E+1' => 10.0,
133
- '+1.0E-1' => 0.1,
134
- '-1.0' => -1.0,
135
- '-1.234' => -1.234,
136
- '-1.0e+1' => -10.0,
137
- '-1.0e-1' => -0.1,
138
- '-1.0E+1' => -10.0,
139
- '-1.0E-1' => -0.1,
140
- '.1' => 0.1,
141
- '.1e+1' => 1.0,
142
- '.1e-1' => 0.01,
143
- '.1E+1' => 1.0,
144
- '.1E-1' => 0.01,
145
- '1e1' => 10.0,
146
- '1E+1' => 10.0,
147
- '+1e-1' => 0.1,
148
- '-1E1' => -10.0,
149
- '-1e-1' => -0.1,
150
- }.each do |value, float|
151
- it "converts #{value.inspect} to a float" do
152
- expect(coerce(value, :float)).to be_kind_of(Float)
153
- expect(coerce(value, :float)).to eq float
154
- end
155
- end
156
-
157
- it 'fails with an invalid string' do
158
- expect { coerce('non-float', :float) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
159
- end
160
-
161
- it 'fails when string starts with e' do
162
- expect { coerce('e1', :float) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
163
- end
164
- end
165
-
166
- describe 'to boolean' do
167
- %w[ 1 on ON t true T TRUE y yes Y YES ].each do |value|
168
- it "converts #{value.inspect} to `true`" do
169
- expect(coerce(value, :boolean)).to eq true
170
- end
171
- end
172
-
173
- %w[ 0 off OFF f false F FALSE n no N NO ].each do |value|
174
- it "converts #{value.inspect} to `false`" do
175
- expect(coerce(value, :boolean)).to eq false
176
- end
177
- end
178
-
179
- it 'fails with an invalid boolean string' do
180
- expect { coerce('non-boolean', :boolean) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
181
- end
182
- end
183
-
184
- describe 'to symbol' do
185
- it 'converts strings to symbols' do
186
- expect(coerce('a', :symbol)).to eq :a
187
- expect(coerce('nice_symbol', :symbol)).to eq :nice_symbol
188
- end
189
- end
190
-
191
- describe 'to date' do
192
- it 'converts string to date' do
193
- date = coerce('2019-03-22', :date)
194
-
195
- expect(date).to be_instance_of(Date)
196
- expect(date.year).to eq 2019
197
- expect(date.month).to eq 3
198
- expect(date.day).to eq 22
199
- end
200
-
201
- it 'converts other string formats to date' do
202
- expect(coerce('March 22nd, 2019', :date)).to eq Date.parse('2019-03-22')
203
- expect(coerce('Sat, March 23rd, 2019', :date)).to eq Date.parse('2019-03-23')
204
- end
205
-
206
- it 'fails with an invalid string' do
207
- expect { coerce('non-date', :date) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
208
- end
209
- end
210
-
211
- describe 'to time' do
212
- it 'converts string to time without time part' do
213
- time = coerce("2019-03-22", :time)
214
-
215
- expect(time).to be_instance_of(Time)
216
- expect(time.year).to eq 2019
217
- expect(time.month).to eq 3
218
- expect(time.day).to eq 22
219
- expect(time.hour).to eq 0
220
- expect(time.min).to eq 0
221
- expect(time.sec).to eq 0
222
- end
223
-
224
- it 'converts string to time with time portion' do
225
- time = coerce("March 22nd, 2019 9:30:55", :time)
226
-
227
- expect(time).to be_instance_of(Time)
228
- expect(time.year).to eq 2019
229
- expect(time.month).to eq 3
230
- expect(time.day).to eq 22
231
- expect(time.hour).to eq 9
232
- expect(time.min).to eq 30
233
- expect(time.sec).to eq 55
234
- end
235
-
236
- it 'fails with an invalid string' do
237
- expect { coerce('2999', :time) }.to raise_error(ENVied::Coercer::UnsupportedCoercion)
238
- end
239
- end
240
-
241
- describe 'to array' do
242
- it 'converts strings to array' do
243
- {
244
- 'a,b' => ['a','b'],
245
- ' a, b' => [' a',' b'],
246
- 'apples,and\, of course\, pears' => ['apples','and, of course, pears'],
247
- }.each do |value, array|
248
- expect(coerce(value, :array)).to eq array
249
- end
250
- end
251
- end
252
-
253
- describe 'to hash' do
254
- it 'converts strings to hashes' do
255
- {
256
- 'a=1' => {'a' => '1'},
257
- 'a=1&b=2' => {'a' => '1', 'b' => '2'},
258
- 'a=&b=2' => {'a' => '', 'b' => '2'},
259
- 'a&b=2' => {'a' => nil, 'b' => '2'},
260
- }.each do |value, hash|
261
- expect(coerce(value, :hash)).to eq hash
262
- end
263
- end
264
- end
265
-
266
- describe 'to uri' do
267
- it 'converts strings to uris' do
268
- expect(coerce('https://www.google.com', :uri)).to be_a(URI)
269
- expect(coerce('https://www.google.com', :uri).scheme).to eq 'https'
270
- expect(coerce('https://www.google.com', :uri).host).to eq 'www.google.com'
271
- end
272
- end
273
- end
274
- end
@@ -1,113 +0,0 @@
1
- RSpec.describe ENVied::Configuration do
2
- it { is_expected.to respond_to :variable }
3
- it { is_expected.to respond_to :group }
4
- it { is_expected.to respond_to :enable_defaults! }
5
- it { is_expected.to respond_to :defaults_enabled? }
6
-
7
- def with_envfile(**options, &block)
8
- @config = ENVied::Configuration.new(options, &block)
9
- end
10
- attr_reader :config
11
-
12
- describe 'variables' do
13
- it 'results in an added variable' do
14
- with_envfile do
15
- variable :foo, :boolean
16
- end
17
-
18
- expect(config.variables).to include ENVied::Variable.new(:foo, :boolean, group: :default)
19
- end
20
-
21
- it 'sets string as default type when no type is given' do
22
- with_envfile do
23
- variable :bar
24
- end
25
-
26
- expect(config.variables).to include ENVied::Variable.new(:bar, :string, default: nil, group: :default)
27
- end
28
-
29
- it 'sets a default value when specified' do
30
- with_envfile do
31
- variable :bar, default: 'bar'
32
- end
33
-
34
- expect(config.variables).to include ENVied::Variable.new(:bar, :string, default: 'bar', group: :default)
35
- end
36
-
37
- it 'sets specific group for variable' do
38
- with_envfile do
39
- group :production do
40
- variable :SECRET_KEY_BASE
41
- end
42
- end
43
-
44
- expect(config.variables).to include ENVied::Variable.new(:SECRET_KEY_BASE, :string, group: :production)
45
- end
46
-
47
- it 'sets the same variable for multiple groups' do
48
- with_envfile do
49
- group :development, :test do
50
- variable :DISABLE_PRY, :boolean, default: 'false'
51
- end
52
- end
53
-
54
- expect(config.variables).to eq [
55
- ENVied::Variable.new(:DISABLE_PRY, :boolean, default: 'false', group: :development),
56
- ENVied::Variable.new(:DISABLE_PRY, :boolean, default: 'false', group: :test)
57
- ]
58
- end
59
- end
60
-
61
- describe 'defaults' do
62
- it 'is disabled by default' do
63
- expect(subject.defaults_enabled?).to eq false
64
- end
65
-
66
- it 'can be enabled with an ENV variable' do
67
- allow(ENV).to receive(:[]).with("ENVIED_ENABLE_DEFAULTS").and_return("true")
68
- expect(subject.defaults_enabled?).to eq true
69
- end
70
-
71
- it 'can be enabled through a config option' do
72
- with_envfile(enable_defaults: true) { }
73
-
74
- expect(config.defaults_enabled?).to eq true
75
- end
76
-
77
- describe '#enable_defaults!' do
78
- it 'can be enabled in a block by calling `enable_defaults!`' do
79
- with_envfile do
80
- enable_defaults!
81
- end
82
-
83
- expect(config.defaults_enabled?).to eq true
84
- end
85
-
86
- it 'can be enabled by calling `enable_defaults!` with a Proc' do
87
- with_envfile do
88
- enable_defaults! { true }
89
- end
90
-
91
- expect(config.defaults_enabled?).to eq true
92
- end
93
-
94
- it 'defaults to true with no arguments' do
95
- expect {
96
- subject.enable_defaults!
97
- }.to change { subject.defaults_enabled? }.from(false).to(true)
98
- end
99
-
100
- it 'can be passed a boolean value' do
101
- expect {
102
- subject.enable_defaults!(true)
103
- }.to change { subject.defaults_enabled? }.from(false).to(true)
104
- end
105
-
106
- it 'can be passed a block' do
107
- expect {
108
- subject.enable_defaults! { true }
109
- }.to change { subject.defaults_enabled? }.from(false).to(true)
110
- end
111
- end
112
- end
113
- end
@@ -1,22 +0,0 @@
1
- RSpec.describe ENVied::EnvVarExtractor do
2
-
3
- describe "#capture_variables" do
4
- def capture_variables(text)
5
- described_class.new.capture_variables(text)
6
- end
7
-
8
- {
9
- %{self.a = ENV['A']} => %w(A),
10
- %{self.a = ENV["A"]} => %w(A),
11
- %{self.a = ENV.fetch('A')]} => %w(A),
12
- %{self.a = ENV.fetch("A")]} => %w(A),
13
- %{# self.a = ENV["A"]} => %w(A),
14
- %{self.a = ENV["A"] && self.b = ENV["B"]} => %w(A B),
15
- %{self.a = ENV["A3"]} => %w(A3)
16
- }.each do |line, expected|
17
- it "captures #{expected} from #{line.inspect}" do
18
- expect(capture_variables(line)).to contain_exactly(*expected)
19
- end
20
- end
21
- end
22
- end
@@ -1,339 +0,0 @@
1
- RSpec.describe ENVied do
2
- describe 'class' do
3
- subject { described_class }
4
- it { is_expected.to respond_to :require }
5
- end
6
-
7
- def reset_envied
8
- ENVied.instance_eval do
9
- @env = nil
10
- @config = nil
11
- end
12
- end
13
-
14
- context 'configured' do
15
-
16
- before do
17
- reset_envied
18
- end
19
-
20
- def set_ENV(env = {})
21
- stub_const("ENV", env)
22
- end
23
-
24
- def configure(**options, &block)
25
- @config = ENVied::Configuration.new(options, &block)
26
- end
27
-
28
- def configured_with(**hash)
29
- @config = ENVied::Configuration.new.tap do |config|
30
- hash.each do |name, type|
31
- config.variable(name, type)
32
- end
33
- end
34
- end
35
-
36
- def envied_require(*args, **options)
37
- options[:config] = @config || ENVied::Configuration.new # Prevent `Configuration.load` from being called
38
- ENVied.require(*args, **options)
39
- end
40
-
41
- it 'does respond to configured variables' do
42
- set_ENV('A' => '1')
43
- configured_with(A: :integer)
44
- envied_require
45
-
46
- expect(described_class).to respond_to :A
47
- end
48
-
49
- it 'does not respond to unconfigured variables' do
50
- set_ENV('A' => '1')
51
- configured_with
52
- envied_require
53
-
54
- expect(described_class).to_not respond_to :B
55
- end
56
-
57
- it 'sets ENVied.config' do
58
- set_ENV('A' => '1')
59
- configured_with(A: :integer)
60
- envied_require
61
-
62
- expect(ENVied.config).to be_instance_of(ENVied::Configuration)
63
- end
64
-
65
- context 'ENV contains not all configured variables' do
66
- before do
67
- set_ENV
68
- configured_with(A: :integer)
69
- end
70
-
71
- specify do
72
- expect {
73
- envied_require
74
- }.to raise_error(RuntimeError, 'The following environment variables should be set: A.')
75
- end
76
- end
77
-
78
- context 'ENV variables are not coercible' do
79
- before do
80
- set_ENV('A' => 'NaN', 'B' => 'invalid')
81
- configured_with(A: :integer, B: :boolean)
82
- end
83
-
84
- specify do
85
- expect {
86
- envied_require
87
- }.to raise_error(
88
- RuntimeError,
89
- 'The following environment variables are not coercible: A with "NaN" (integer), B with "invalid" (boolean).'
90
- )
91
- end
92
- end
93
-
94
- context 'configuring' do
95
- it 'raises error when configuring variable of unknown type' do
96
- expect {
97
- configured_with(A: :fixnum)
98
- }.to raise_error(ArgumentError, ":fixnum is not a supported type. Should be one of #{ENVied::Coercer.supported_types}")
99
- end
100
- end
101
-
102
- # TODO: review needed, doesn't make sense?
103
- context 'bug: default value "false" is not coercible' do
104
- before do
105
- configure(enable_defaults: true) do
106
- variable :FORCE_SSL, :boolean, default: true
107
- end
108
- end
109
-
110
- specify do
111
- expect {
112
- envied_require
113
- }.not_to raise_error
114
- end
115
- end
116
-
117
- describe 'defaults' do
118
- describe 'assigning' do
119
- it 'sets a default value for ENV variable' do
120
- configure(enable_defaults: true) do
121
- variable :A, :integer, default: '1'
122
- end
123
- envied_require
124
-
125
- expect(described_class.A).to eq 1
126
- end
127
-
128
- it 'sets a default value from calling a proc for ENV variable' do
129
- configure(enable_defaults: true) do
130
- variable :A, :integer, default: proc { "1" }
131
- end
132
- envied_require
133
-
134
- expect(described_class.A).to eq 1
135
- end
136
-
137
- it 'ignores setting defaults if they are disabled' do
138
- set_ENV
139
- configure(enable_defaults: false) do
140
- variable :A, :integer, default: "1"
141
- variable :B, :integer, default: "1"
142
- end
143
-
144
- expect {
145
- envied_require
146
- }.to raise_error(RuntimeError, 'The following environment variables should be set: A, B.')
147
- end
148
-
149
- it 'ignores a default value if ENV variable is already provided' do
150
- set_ENV('A' => '2')
151
- configure(enable_defaults: true) do
152
- variable :A, :integer, default: "1"
153
- end
154
- envied_require
155
-
156
- expect(described_class.A).to eq 2
157
- end
158
-
159
- it 'can set a default value via a proc that references another ENV variable' do
160
- set_ENV('A' => '1')
161
- configure(enable_defaults: true) do
162
- variable :A, :integer
163
- variable :B, :integer, default: proc {|env| env.A * 2 }
164
- end
165
- envied_require
166
-
167
- expect(described_class.B).to eq 2
168
- end
169
- end
170
- end
171
-
172
- describe ".required?" do
173
- # TODO: change to always return boolean
174
- it 'returns true-ish if `ENVied.require` was called' do
175
- expect {
176
- envied_require
177
- }.to change { ENVied.required? }.from(nil).to(anything)
178
- end
179
- end
180
-
181
- describe "groups" do
182
- context 'a variable in a group' do
183
- before do
184
- set_ENV
185
- configure do
186
- variable :MORE
187
-
188
- group :foo do
189
- variable :BAR
190
- end
191
- group :moo do
192
- variable :BAT
193
- end
194
- end
195
- end
196
-
197
- it 'is required when requiring the groups passed as a delimited string' do
198
- expect {
199
- envied_require('foo,moo')
200
- }.to raise_error(RuntimeError, 'The following environment variables should be set: BAR, BAT.')
201
- end
202
-
203
- it 'is required when requiring the group' do
204
- [:foo, 'foo'].each do |group|
205
- expect {
206
- envied_require(group)
207
- }.to raise_error(RuntimeError, 'The following environment variables should be set: BAR.')
208
- end
209
- end
210
-
211
- it 'is not required when requiring another group' do
212
- [:bat, 'bat'].each do |group|
213
- expect {
214
- envied_require(group)
215
- }.to_not raise_error
216
- end
217
- end
218
-
219
- it 'will not define variables not part of the default group' do
220
- set_ENV('MORE' => 'yes')
221
- envied_require(:default)
222
-
223
- expect {
224
- described_class.BAR
225
- }.to raise_error(NoMethodError)
226
- end
227
-
228
- it 'takes ENV["ENVIED_GROUPS"] into account when nothing is passed to require' do
229
- set_ENV('ENVIED_GROUPS' => 'foo')
230
- expect {
231
- envied_require
232
- }.to raise_error(RuntimeError, 'The following environment variables should be set: BAR.')
233
- end
234
-
235
- it 'will define variables in the default group when nothing is passed to require' do
236
- set_ENV('MORE' => 'yes')
237
- envied_require
238
-
239
- expect(described_class.MORE).to eq 'yes'
240
- end
241
-
242
- it 'requires variables without a group when requiring the default group' do
243
- [:default, 'default'].each do |group|
244
- expect {
245
- envied_require(group)
246
- }.to raise_error(RuntimeError, 'The following environment variables should be set: MORE.')
247
- end
248
- end
249
- end
250
-
251
- context 'a variable in multiple groups' do
252
- before do
253
- set_ENV
254
- configure do
255
- variable :MORE
256
-
257
- group :foo, :moo do
258
- variable :BAR
259
- end
260
- end
261
- end
262
-
263
- it 'is required when requiring any of the groups' do
264
- expect {
265
- envied_require(:foo)
266
- }.to raise_error(RuntimeError, 'The following environment variables should be set: BAR.')
267
-
268
- expect {
269
- envied_require(:moo)
270
- }.to raise_error(RuntimeError, 'The following environment variables should be set: BAR.')
271
- end
272
- end
273
-
274
- describe 'Hashable' do
275
- before do
276
- set_ENV('FOO' => 'a=1&b=&c', 'BAR' => '')
277
- configure do
278
- variable :FOO, :hash
279
- variable :BAR, :hash
280
- end
281
- envied_require
282
- end
283
-
284
- it 'yields hash from string' do
285
- expect(ENVied.FOO).to eq({ 'a' => '1', 'b' => '', 'c' => nil })
286
- end
287
-
288
- it 'yields hash from an empty string' do
289
- expect(ENVied.BAR).to eq({})
290
- end
291
-
292
- context 'with defaults enabled' do
293
- before do
294
- set_ENV
295
- configure(enable_defaults: true) do
296
- variable :BAZ, :hash
297
- end
298
- end
299
-
300
- it 'has no default by default' do
301
- # fixes a bug where variables of type :Hash had a default even
302
- # when none was configured.
303
- expect { envied_require }.to raise_error(RuntimeError, 'The following environment variables should be set: BAZ.')
304
- end
305
- end
306
- end
307
-
308
- describe 'Arrayable' do
309
- before do
310
- set_ENV('MORE' => 'a, b, and\, c')
311
- configure do
312
- variable :MORE, :array
313
- end
314
- envied_require
315
- end
316
-
317
- it 'yields array from string' do
318
- expect(ENVied.MORE).to eq ['a',' b',' and, c']
319
- end
320
- end
321
-
322
- describe 'URIable' do
323
- before do
324
- set_ENV('SITE_URL' => 'https://www.google.com')
325
- configure do
326
- variable :SITE_URL, :uri
327
- end
328
- envied_require
329
- end
330
-
331
- it 'yields a URI from string' do
332
- expect(ENVied.SITE_URL).to be_a URI
333
- expect(ENVied.SITE_URL.scheme).to eq 'https'
334
- expect(ENVied.SITE_URL.host).to eq 'www.google.com'
335
- end
336
- end
337
- end
338
- end
339
- end