envied 0.9.3 → 0.10.0.alpha1

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,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