env_bang 1.0.0.pre.rc.1 → 2.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +39 -0
- data/Gemfile +3 -2
- data/README.md +7 -9
- data/lib/env_bang/version.rb +1 -1
- data/lib/env_bang.rb +34 -4
- data/test/env_bang_test.rb +226 -57
- data/test/test_helper.rb +16 -8
- metadata +3 -3
- data/.travis.yml +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '094ce7c346a763599ef55ab0256e99cdbed2d4f3059782cb2078ce8f5ff42502'
|
4
|
+
data.tar.gz: 353125d00af13bcb825fba521115a53d414d78bfc2e80cc7c8573051ee7c45a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 878b656b6090bdbbca837f260032a99edb2a34a50890681d2d88f9ce0e071df2a9c860778288478b7f1627acee4ce7f38efe5f55f469da1806e5fe2ed1850090
|
7
|
+
data.tar.gz: c9045031fd3209dc99605ec3a59c67e579d937b658250e4dbd29b958ddd8ed0fe0483f1c850ae59f0cf93e558420674e10ed32bc506a122186978cdd10cddfa5
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Use the latest 2.1 version of CircleCI pipeline process engine.
|
2
|
+
# See: https://circleci.com/docs/2.0/configuration-reference
|
3
|
+
version: 2.1
|
4
|
+
|
5
|
+
orbs:
|
6
|
+
ruby: circleci/ruby@2.0.0
|
7
|
+
coveralls: coveralls/coveralls@2.1.0
|
8
|
+
|
9
|
+
# Define a job to be invoked later in a workflow.
|
10
|
+
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
|
11
|
+
jobs:
|
12
|
+
test:
|
13
|
+
parameters:
|
14
|
+
ruby-version:
|
15
|
+
type: string
|
16
|
+
docker:
|
17
|
+
# replace with your preferred image
|
18
|
+
- image: cimg/ruby:<< parameters.ruby-version >>
|
19
|
+
resource_class: small
|
20
|
+
environment:
|
21
|
+
COVERAGE: Summary
|
22
|
+
steps:
|
23
|
+
- checkout
|
24
|
+
- run: bundle install
|
25
|
+
- run: bundle exec rake
|
26
|
+
- coveralls/upload:
|
27
|
+
coverage_file: coverage/lcov.info
|
28
|
+
|
29
|
+
# Invoke jobs via workflows
|
30
|
+
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
|
31
|
+
workflows:
|
32
|
+
buidle_and_test:
|
33
|
+
jobs:
|
34
|
+
- test:
|
35
|
+
matrix:
|
36
|
+
parameters:
|
37
|
+
# https://github.com/CircleCI-Public/cimg-ruby
|
38
|
+
# only supports the last three ruby versions
|
39
|
+
ruby-version: ["2.6", "2.7", "3.0", "3.2"]
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
# ENV!
|
2
2
|
|
3
|
-
|
3
|
+
Verify correctness of environment configuration at startup time.
|
4
4
|
|
5
|
-
[![Gem Version](https://img.shields.io/gem/v/env_bang
|
6
|
-
[![Build Status](https://img.shields.io/
|
7
|
-
[![Maintainability](https://
|
8
|
-
[![Coverage Status](https://img.shields.io/
|
5
|
+
[![Gem Version](https://img.shields.io/gem/v/env_bang?logo=rubygems)](https://rubygems.org/gems/env_bang)
|
6
|
+
[![Build Status](https://img.shields.io/circleci/build/github/jcamenisch/ENV_BANG/main)](https://dl.circleci.com/status-badge/redirect/gh/jcamenisch/ENV_BANG/tree/main)
|
7
|
+
[![Maintainability](https://img.shields.io/codeclimate/maintainability/jcamenisch/ENV_BANG?logo=codeclimate)](https://codeclimate.com/github/jcamenisch/ENV_BANG)
|
8
|
+
[![Coverage Status](https://img.shields.io/coverallsCoverage/github/jcamenisch/ENV_BANG?logo=coveralls)](https://coveralls.io/r/jcamenisch/ENV_BANG)
|
9
9
|
|
10
10
|
ENV! provides a thin wrapper around ENV to accomplish a few things:
|
11
11
|
|
12
12
|
- Provide a central place to specify all your app’s environment variables.
|
13
|
-
- Fail loudly and helpfully if any environment variables are missing.
|
14
|
-
- Prevent an application from starting up with
|
15
|
-
(This is especially helpful in environments like Heroku, as your app will
|
16
|
-
continue running the old code until the server is configured for a new revision.)
|
13
|
+
- Fail loudly and helpfully if any environment variables are missing or invalid.
|
14
|
+
- Prevent an application from starting up with invalid environment variables.
|
17
15
|
|
18
16
|
## Installation
|
19
17
|
|
data/lib/env_bang/version.rb
CHANGED
data/lib/env_bang.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
require "env_bang/version"
|
2
2
|
require "env_bang/classes"
|
3
3
|
require "env_bang/formatter"
|
4
|
+
require "forwardable"
|
4
5
|
|
5
6
|
class ENV_BANG
|
6
7
|
class << self
|
8
|
+
extend Forwardable
|
9
|
+
include Enumerable
|
10
|
+
|
7
11
|
def config(&block)
|
8
12
|
instance_eval(&block)
|
9
13
|
end
|
@@ -48,10 +52,6 @@ class ENV_BANG
|
|
48
52
|
Classes.cast ENV[var], vars[var]
|
49
53
|
end
|
50
54
|
|
51
|
-
def method_missing(method, *args, &block)
|
52
|
-
ENV.send(method, *args, &block)
|
53
|
-
end
|
54
|
-
|
55
55
|
def add_class(klass, &block)
|
56
56
|
Classes.send :define_singleton_method, klass.to_s, &block
|
57
57
|
end
|
@@ -63,6 +63,36 @@ class ENV_BANG
|
|
63
63
|
Classes.default_class
|
64
64
|
end
|
65
65
|
end
|
66
|
+
|
67
|
+
def to_h
|
68
|
+
keys.map { |k| [k, self[k]] }.to_h
|
69
|
+
end
|
70
|
+
|
71
|
+
alias to_hash to_h
|
72
|
+
|
73
|
+
####################################
|
74
|
+
# Implement Hash-like read methods #
|
75
|
+
####################################
|
76
|
+
|
77
|
+
def_delegators :to_h,
|
78
|
+
:each, :assoc, :each_pair, :each_value, :empty?, :fetch,
|
79
|
+
:invert, :key, :rassoc, :values_at
|
80
|
+
|
81
|
+
def_delegators :vars, :each_key, :has_key?, :key?, :length, :size
|
82
|
+
|
83
|
+
def slice(*requested_keys)
|
84
|
+
(requested_keys & keys).map { |k| [k, self[k]] }.to_h
|
85
|
+
end
|
86
|
+
|
87
|
+
def except(*exceptions)
|
88
|
+
slice(*(keys - exceptions))
|
89
|
+
end
|
90
|
+
|
91
|
+
def value?(value)
|
92
|
+
values.include?(value)
|
93
|
+
end
|
94
|
+
|
95
|
+
alias has_value? value?
|
66
96
|
end
|
67
97
|
end
|
68
98
|
|
data/test/env_bang_test.rb
CHANGED
@@ -8,13 +8,13 @@ describe ENV_BANG do
|
|
8
8
|
|
9
9
|
it "Raises exception if unconfigured ENV var requested" do
|
10
10
|
ENV['UNCONFIGURED'] = 'unconfigured'
|
11
|
-
|
11
|
+
_{ ENV!['UNCONFIGURED'] }.must_raise KeyError
|
12
12
|
end
|
13
13
|
|
14
14
|
it "Raises exception if configured ENV var is not present" do
|
15
15
|
ENV.delete('NOT_PRESENT')
|
16
16
|
|
17
|
-
|
17
|
+
_{
|
18
18
|
ENV!.config do
|
19
19
|
use 'NOT_PRESENT'
|
20
20
|
end
|
@@ -22,12 +22,12 @@ describe ENV_BANG do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "Raises exception immediately if value is invalid for the required type" do
|
25
|
-
|
25
|
+
_{
|
26
26
|
ENV['NOT_A_DATE'] = '2017-02-30'
|
27
27
|
ENV!.use 'NOT_A_DATE', class: Date
|
28
28
|
}.must_raise ArgumentError
|
29
29
|
|
30
|
-
|
30
|
+
_{
|
31
31
|
ENV!.use 'NOT_A_DATE_DEFAULT', class: Date, default: '2017-02-31'
|
32
32
|
}.must_raise ArgumentError
|
33
33
|
end
|
@@ -38,7 +38,7 @@ describe ENV_BANG do
|
|
38
38
|
ENV!.config do
|
39
39
|
use 'WASNT_PRESENT', default: 'a default value'
|
40
40
|
end
|
41
|
-
ENV!['WASNT_PRESENT'].must_equal 'a default value'
|
41
|
+
_(ENV!['WASNT_PRESENT']).must_equal 'a default value'
|
42
42
|
end
|
43
43
|
|
44
44
|
it "Returns actual value from ENV if present" do
|
@@ -47,7 +47,7 @@ describe ENV_BANG do
|
|
47
47
|
ENV!.config do
|
48
48
|
use 'PRESENT', default: "You won't need this."
|
49
49
|
end
|
50
|
-
ENV!['PRESENT'].must_equal 'present in environment'
|
50
|
+
_(ENV!['PRESENT']).must_equal 'present in environment'
|
51
51
|
end
|
52
52
|
|
53
53
|
describe "Type casting" do
|
@@ -61,14 +61,14 @@ describe ENV_BANG do
|
|
61
61
|
ENV['INTEGER'] = integer
|
62
62
|
ENV!.use 'INTEGER', class: Integer
|
63
63
|
|
64
|
-
ENV!['INTEGER'].must_equal integer.to_i
|
64
|
+
_(ENV!['INTEGER']).must_equal integer.to_i
|
65
65
|
end
|
66
66
|
|
67
67
|
it "Casts Symbols" do
|
68
68
|
ENV['SYMBOL'] = 'symbol'
|
69
69
|
ENV!.use 'SYMBOL', class: Symbol
|
70
70
|
|
71
|
-
ENV!['SYMBOL'].must_equal :symbol
|
71
|
+
_(ENV!['SYMBOL']).must_equal :symbol
|
72
72
|
end
|
73
73
|
|
74
74
|
it "Casts Floats" do
|
@@ -76,29 +76,29 @@ describe ENV_BANG do
|
|
76
76
|
ENV['FLOAT'] = float
|
77
77
|
ENV!.use 'FLOAT', class: Float
|
78
78
|
|
79
|
-
ENV!['FLOAT'].must_equal float.to_f
|
80
|
-
ENV!['FLOAT'].class.must_equal Float
|
79
|
+
_(ENV!['FLOAT']).must_equal float.to_f
|
80
|
+
_(ENV!['FLOAT'].class).must_equal Float
|
81
81
|
end
|
82
82
|
|
83
83
|
it "Casts Arrays" do
|
84
84
|
ENV['ARRAY'] = 'one,two , three, four'
|
85
85
|
ENV!.use 'ARRAY', class: Array
|
86
86
|
|
87
|
-
ENV!['ARRAY'].must_equal %w[one two three four]
|
87
|
+
_(ENV!['ARRAY']).must_equal %w[one two three four]
|
88
88
|
end
|
89
89
|
|
90
90
|
it "Casts Arrays of Integers" do
|
91
91
|
ENV['INTEGERS'] = integers.join(',')
|
92
92
|
ENV!.use 'INTEGERS', class: Array, of: Integer
|
93
93
|
|
94
|
-
ENV!['INTEGERS'].must_equal integers.map(&:to_i)
|
94
|
+
_(ENV!['INTEGERS']).must_equal integers.map(&:to_i)
|
95
95
|
end
|
96
96
|
|
97
97
|
it "Casts Arrays of Floats" do
|
98
98
|
ENV['FLOATS'] = floats.join(',')
|
99
99
|
ENV!.use 'FLOATS', class: Array, of: Float
|
100
100
|
|
101
|
-
ENV!['FLOATS'].must_equal floats.map(&:to_f)
|
101
|
+
_(ENV!['FLOATS']).must_equal floats.map(&:to_f)
|
102
102
|
end
|
103
103
|
|
104
104
|
it "regression: Casting Array always returns Array" do
|
@@ -106,7 +106,7 @@ describe ENV_BANG do
|
|
106
106
|
ENV!.use 'ARRAY', class: Array
|
107
107
|
|
108
108
|
2.times do
|
109
|
-
ENV!['ARRAY'].must_equal %w[one two three four]
|
109
|
+
_(ENV!['ARRAY']).must_equal %w[one two three four]
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
@@ -114,80 +114,80 @@ describe ENV_BANG do
|
|
114
114
|
ENV['HASH'] = 'one: two, three: http://four.com'
|
115
115
|
ENV!.use 'HASH', class: Hash
|
116
116
|
|
117
|
-
ENV!['HASH'].must_equal({one: 'two', three: 'http://four.com'})
|
117
|
+
_(ENV!['HASH']).must_equal({one: 'two', three: 'http://four.com'})
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'Casts Hashes of Integers' do
|
121
121
|
ENV['INT_HASH'] = 'one: 111, two: 222'
|
122
122
|
ENV!.use 'INT_HASH', class: Hash, of: Integer
|
123
123
|
|
124
|
-
ENV!['INT_HASH'].must_equal({one: 111, two: 222})
|
124
|
+
_(ENV!['INT_HASH']).must_equal({one: 111, two: 222})
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'Casts Hashes with String keys' do
|
128
128
|
ENV['STRKEY_HASH'] = 'one: two, three: four'
|
129
129
|
ENV!.use 'STRKEY_HASH', class: Hash, keys: String
|
130
130
|
|
131
|
-
ENV!['STRKEY_HASH'].must_equal({'one' => 'two', 'three' => 'four'})
|
131
|
+
_(ENV!['STRKEY_HASH']).must_equal({'one' => 'two', 'three' => 'four'})
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'Casts Hashes with alternate separators' do
|
135
135
|
ENV['ALT_HASH'] = 'one:two = three; four,five=six'
|
136
136
|
ENV!.use 'ALT_HASH', class: Hash, sep: ';', val_sep: '='
|
137
137
|
|
138
|
-
ENV!['ALT_HASH'].must_equal({:'one:two' => 'three', :'four,five' => 'six'})
|
138
|
+
_(ENV!['ALT_HASH']).must_equal({:'one:two' => 'three', :'four,five' => 'six'})
|
139
139
|
end
|
140
140
|
|
141
141
|
it "Casts true" do
|
142
142
|
ENV['TRUE'] = truthy_values.sample
|
143
143
|
ENV!.use 'TRUE', class: :boolean
|
144
144
|
|
145
|
-
ENV!['TRUE'].must_equal true
|
145
|
+
_(ENV!['TRUE']).must_equal true
|
146
146
|
end
|
147
147
|
|
148
148
|
it "Casts false" do
|
149
149
|
ENV['FALSE'] = falsey_values.sample
|
150
150
|
ENV!.use 'FALSE', class: :boolean
|
151
151
|
|
152
|
-
ENV!['FALSE'].must_equal false
|
152
|
+
_(ENV!['FALSE']).must_equal false
|
153
153
|
end
|
154
154
|
|
155
155
|
it "converts falsey or empty string to false by default" do
|
156
156
|
ENV['FALSE'] = falsey_values.sample
|
157
157
|
ENV!.use 'FALSE'
|
158
158
|
|
159
|
-
ENV!['FALSE'].must_equal false
|
159
|
+
_(ENV!['FALSE']).must_equal false
|
160
160
|
end
|
161
161
|
|
162
162
|
it "leaves falsey string as string if specified" do
|
163
163
|
ENV['FALSE'] = falsey_values.sample
|
164
164
|
ENV!.use 'FALSE', class: String
|
165
165
|
|
166
|
-
ENV!['FALSE'].class.must_equal String
|
166
|
+
_(ENV!['FALSE'].class).must_equal String
|
167
167
|
end
|
168
168
|
|
169
169
|
it "casts Dates" do
|
170
170
|
ENV['A_DATE'] = '2005-05-05'
|
171
171
|
ENV!.use 'A_DATE', class: Date
|
172
172
|
|
173
|
-
ENV!['A_DATE'].class.must_equal Date
|
174
|
-
ENV!['A_DATE'].must_equal Date.new(2005, 5, 5)
|
173
|
+
_(ENV!['A_DATE'].class).must_equal Date
|
174
|
+
_(ENV!['A_DATE']).must_equal Date.new(2005, 5, 5)
|
175
175
|
end
|
176
176
|
|
177
177
|
it "casts DateTimes" do
|
178
178
|
ENV['A_DATETIME'] = '2005-05-05 5:05pm'
|
179
179
|
ENV!.use 'A_DATETIME', class: DateTime
|
180
180
|
|
181
|
-
ENV!['A_DATETIME'].class.must_equal DateTime
|
182
|
-
ENV!['A_DATETIME'].must_equal DateTime.new(2005, 5, 5, 17, 5)
|
181
|
+
_(ENV!['A_DATETIME'].class).must_equal DateTime
|
182
|
+
_(ENV!['A_DATETIME']).must_equal DateTime.new(2005, 5, 5, 17, 5)
|
183
183
|
end
|
184
184
|
|
185
185
|
it "casts Times" do
|
186
186
|
ENV['A_TIME'] = '2005-05-05 5:05pm'
|
187
187
|
ENV!.use 'A_TIME', class: Time
|
188
188
|
|
189
|
-
ENV!['A_TIME'].class.must_equal Time
|
190
|
-
ENV!['A_TIME'].must_equal Time.new(2005, 5, 5, 17, 5)
|
189
|
+
_(ENV!['A_TIME'].class).must_equal Time
|
190
|
+
_(ENV!['A_TIME']).must_equal Time.new(2005, 5, 5, 17, 5)
|
191
191
|
end
|
192
192
|
|
193
193
|
it "casts Regexps" do
|
@@ -195,51 +195,51 @@ describe ENV_BANG do
|
|
195
195
|
ENV['A_REGEX'] = '^(this|is|a|[^tes.*\|]t.\.\*/\\\)$'
|
196
196
|
ENV!.use 'A_REGEX', class: Regexp
|
197
197
|
|
198
|
-
ENV!['A_REGEX'].class.must_equal Regexp
|
199
|
-
ENV!['A_REGEX'].must_equal(/^(this|is|a|[^tes.*\|]t.\.\*\/\\)$/)
|
198
|
+
_(ENV!['A_REGEX'].class).must_equal Regexp
|
199
|
+
_(ENV!['A_REGEX']).must_equal(/^(this|is|a|[^tes.*\|]t.\.\*\/\\)$/)
|
200
200
|
end
|
201
201
|
|
202
202
|
it "casts inclusive Ranges of Integers by default" do
|
203
203
|
ENV['A_RANGE'] = '1..100'
|
204
204
|
ENV!.use 'A_RANGE', class: Range
|
205
205
|
|
206
|
-
ENV!['A_RANGE'].class.must_equal Range
|
207
|
-
ENV!['A_RANGE'].must_equal 1..100
|
206
|
+
_(ENV!['A_RANGE'].class).must_equal Range
|
207
|
+
_(ENV!['A_RANGE']).must_equal 1..100
|
208
208
|
end
|
209
209
|
|
210
210
|
it "casts exclusive Ranges as directed" do
|
211
211
|
ENV['EXCLUSIVE_RANGE'] = '1..100'
|
212
212
|
ENV!.use 'EXCLUSIVE_RANGE', class: Range, exclusive: true
|
213
213
|
|
214
|
-
ENV!['EXCLUSIVE_RANGE'].must_equal 1...100
|
214
|
+
_(ENV!['EXCLUSIVE_RANGE']).must_equal 1...100
|
215
215
|
|
216
216
|
ENV['ANOTHER_EXCLUSIVE_RANGE'] = '1...100'
|
217
217
|
ENV!.use 'ANOTHER_EXCLUSIVE_RANGE', class: Range, exclusive: true
|
218
218
|
|
219
|
-
ENV!['ANOTHER_EXCLUSIVE_RANGE'].must_equal 1...100
|
219
|
+
_(ENV!['ANOTHER_EXCLUSIVE_RANGE']).must_equal 1...100
|
220
220
|
end
|
221
221
|
|
222
222
|
it "casts Ranges of floats" do
|
223
223
|
ENV['FLOAT_RANGE'] = '1.5..100.7'
|
224
224
|
ENV!.use 'FLOAT_RANGE', class: Range, of: Float
|
225
225
|
|
226
|
-
ENV!['FLOAT_RANGE'].must_equal 1.5..100.7
|
226
|
+
_(ENV!['FLOAT_RANGE']).must_equal 1.5..100.7
|
227
227
|
end
|
228
228
|
|
229
229
|
it "casts Ranges of strings" do
|
230
230
|
ENV['FLOAT_RANGE'] = 'az..za'
|
231
231
|
ENV!.use 'FLOAT_RANGE', class: Range, of: String
|
232
232
|
|
233
|
-
ENV!['FLOAT_RANGE'].must_equal 'az'..'za'
|
233
|
+
_(ENV!['FLOAT_RANGE']).must_equal 'az'..'za'
|
234
234
|
end
|
235
235
|
|
236
236
|
it "allows default class to be overridden" do
|
237
|
-
ENV!.default_class.must_equal :StringUnlessFalsey
|
237
|
+
_(ENV!.default_class).must_equal :StringUnlessFalsey
|
238
238
|
ENV!.config { default_class String }
|
239
239
|
ENV['FALSE'] = falsey_values.sample
|
240
240
|
ENV!.use 'FALSE', class: String
|
241
241
|
|
242
|
-
ENV!['FALSE'].class.must_equal String
|
242
|
+
_(ENV!['FALSE'].class).must_equal String
|
243
243
|
end
|
244
244
|
|
245
245
|
it "allows addition of custom types" do
|
@@ -254,7 +254,7 @@ describe ENV_BANG do
|
|
254
254
|
use :NUMBER_SET, class: Set, of: Integer
|
255
255
|
end
|
256
256
|
|
257
|
-
ENV!['NUMBER_SET'].must_equal Set.new [1, 3, 5, 7, 9]
|
257
|
+
_(ENV!['NUMBER_SET']).must_equal Set.new [1, 3, 5, 7, 9]
|
258
258
|
end
|
259
259
|
|
260
260
|
describe "Kernel casting delegators" do
|
@@ -262,53 +262,53 @@ describe ENV_BANG do
|
|
262
262
|
ENV['A_INTEGER'] = '-123'
|
263
263
|
ENV!.use 'A_INTEGER', class: Integer
|
264
264
|
|
265
|
-
ENV!['A_INTEGER'].must_equal(-123)
|
265
|
+
_(ENV!['A_INTEGER']).must_equal(-123)
|
266
266
|
end
|
267
267
|
|
268
268
|
it "casts Floats" do
|
269
269
|
ENV['A_FLOAT'] = '123.456'
|
270
270
|
ENV!.use 'A_FLOAT', class: Float
|
271
271
|
|
272
|
-
ENV!['A_FLOAT'].must_equal 123.456
|
272
|
+
_(ENV!['A_FLOAT']).must_equal 123.456
|
273
273
|
end
|
274
274
|
|
275
275
|
it "casts Strings" do
|
276
276
|
ENV['A_STRING'] = 'What do I write here?'
|
277
277
|
ENV!.use 'A_STRING', class: String
|
278
|
-
ENV!['A_STRING'].must_equal 'What do I write here?'
|
278
|
+
_(ENV!['A_STRING']).must_equal 'What do I write here?'
|
279
279
|
end
|
280
280
|
|
281
281
|
it "casts Rationals" do
|
282
282
|
ENV['A_RATIONAL'] = '3/32'
|
283
283
|
ENV!.use 'A_RATIONAL', class: Rational
|
284
284
|
|
285
|
-
ENV!['A_RATIONAL'].class.must_equal Rational
|
286
|
-
ENV!['A_RATIONAL'].must_equal 3.to_r/32
|
287
|
-
ENV!['A_RATIONAL'].to_s.must_equal '3/32'
|
285
|
+
_(ENV!['A_RATIONAL'].class).must_equal Rational
|
286
|
+
_(ENV!['A_RATIONAL']).must_equal 3.to_r/32
|
287
|
+
_(ENV!['A_RATIONAL'].to_s).must_equal '3/32'
|
288
288
|
end
|
289
289
|
|
290
290
|
it "casts Complexes" do
|
291
291
|
ENV['A_COMPLEX'] = '123+4i'
|
292
292
|
ENV!.use 'A_COMPLEX', class: Complex
|
293
293
|
|
294
|
-
ENV!['A_COMPLEX'].class.must_equal Complex
|
295
|
-
ENV!['A_COMPLEX'].to_s.must_equal '123+4i'
|
294
|
+
_(ENV!['A_COMPLEX'].class).must_equal Complex
|
295
|
+
_(ENV!['A_COMPLEX'].to_s).must_equal '123+4i'
|
296
296
|
end
|
297
297
|
|
298
298
|
it "casts Pathnames" do
|
299
299
|
ENV['A_PATHNAME'] = '~/.git/config'
|
300
300
|
ENV!.use 'A_PATHNAME', class: Pathname
|
301
301
|
|
302
|
-
ENV!['A_PATHNAME'].class.must_equal Pathname
|
303
|
-
ENV!['A_PATHNAME'].to_s.must_equal '~/.git/config'
|
302
|
+
_(ENV!['A_PATHNAME'].class).must_equal Pathname
|
303
|
+
_(ENV!['A_PATHNAME'].to_s).must_equal '~/.git/config'
|
304
304
|
end
|
305
305
|
|
306
306
|
it "casts URIs" do
|
307
307
|
ENV['A_URI'] = 'http://www.example.com/path/to/nowhere'
|
308
308
|
ENV!.use 'A_URI', class: URI
|
309
309
|
|
310
|
-
ENV!['A_URI'].class.must_equal URI::HTTP
|
311
|
-
ENV!['A_URI'].to_s.must_equal 'http://www.example.com/path/to/nowhere'
|
310
|
+
_(ENV!['A_URI'].class).must_equal URI::HTTP
|
311
|
+
_(ENV!['A_URI'].to_s).must_equal 'http://www.example.com/path/to/nowhere'
|
312
312
|
end
|
313
313
|
end
|
314
314
|
end
|
@@ -320,7 +320,7 @@ describe ENV_BANG do
|
|
320
320
|
ENV!.use 'VAR1'
|
321
321
|
ENV!.use 'VAR2'
|
322
322
|
|
323
|
-
ENV!.keys.must_equal %w[VAR1 VAR2]
|
323
|
+
_(ENV!.keys).must_equal %w[VAR1 VAR2]
|
324
324
|
end
|
325
325
|
|
326
326
|
it "provides configured values" do
|
@@ -329,7 +329,7 @@ describe ENV_BANG do
|
|
329
329
|
ENV!.use 'VAR1'
|
330
330
|
ENV!.use 'VAR2'
|
331
331
|
|
332
|
-
ENV!.values.must_equal %w[something something\ else]
|
332
|
+
_(ENV!.values).must_equal %w[something something\ else]
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
@@ -337,18 +337,18 @@ describe ENV_BANG do
|
|
337
337
|
it "Includes provided description in error message" do
|
338
338
|
ENV.delete('NOT_PRESENT')
|
339
339
|
|
340
|
-
e =
|
340
|
+
e = _{
|
341
341
|
ENV!.config do
|
342
342
|
use 'NOT_PRESENT', 'You need a NOT_PRESENT var in your ENV'
|
343
343
|
end
|
344
344
|
}.must_raise(KeyError)
|
345
|
-
e.message.must_include 'You need a NOT_PRESENT var in your ENV'
|
345
|
+
_(e.message).must_include 'You need a NOT_PRESENT var in your ENV'
|
346
346
|
end
|
347
347
|
|
348
348
|
it "Removes indentation from provided descriptions" do
|
349
349
|
ENV.delete('NOT_PRESENT')
|
350
350
|
|
351
|
-
e =
|
351
|
+
e = _{
|
352
352
|
ENV!.config do
|
353
353
|
use 'NOT_PRESENT', <<-DESC
|
354
354
|
This multiline description
|
@@ -358,7 +358,7 @@ describe ENV_BANG do
|
|
358
358
|
DESC
|
359
359
|
end
|
360
360
|
}.must_raise(KeyError)
|
361
|
-
e.message.must_include <<-UNINDENTED
|
361
|
+
_(e.message).must_include <<-UNINDENTED
|
362
362
|
This multiline description
|
363
363
|
has a lot of indentation
|
364
364
|
varying from line to line
|
@@ -366,4 +366,173 @@ describe ENV_BANG do
|
|
366
366
|
UNINDENTED
|
367
367
|
end
|
368
368
|
end
|
369
|
+
|
370
|
+
describe "Enumerable methods" do
|
371
|
+
before do
|
372
|
+
ENV['ONE'] = '1'
|
373
|
+
ENV['A'] = 'A'
|
374
|
+
ENV['INT_HASH'] = 'one: 1, two: 2'
|
375
|
+
ENV['FLOAT'] = '1.234'
|
376
|
+
|
377
|
+
ENV!.config do
|
378
|
+
use 'ONE', class: Integer
|
379
|
+
use 'A', class: String
|
380
|
+
use 'INT_HASH', class: Hash, of: Integer
|
381
|
+
use 'FLOAT', class: Float
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
it "converts keys and parsed values to a Hash" do
|
386
|
+
_(ENV!.to_h).must_equal({
|
387
|
+
'ONE' => 1,
|
388
|
+
'A' => 'A',
|
389
|
+
'INT_HASH' => { one: 1, two: 2 },
|
390
|
+
'FLOAT' => 1.234,
|
391
|
+
})
|
392
|
+
end
|
393
|
+
|
394
|
+
it "Doesn't allow write access via the hash (It's not a reference to internal values)" do
|
395
|
+
h = ENV!.to_h
|
396
|
+
h['A'] = 'changed'
|
397
|
+
_(ENV!['A']).must_equal 'A'
|
398
|
+
end
|
399
|
+
|
400
|
+
it "returns an Array representation of the hash too" do
|
401
|
+
_(ENV!.to_a).must_equal [
|
402
|
+
['ONE', 1],
|
403
|
+
['A', 'A'],
|
404
|
+
['INT_HASH', { one: 1, two: 2 }],
|
405
|
+
['FLOAT', 1.234],
|
406
|
+
]
|
407
|
+
end
|
408
|
+
|
409
|
+
it "implements other Enumerable methods too" do
|
410
|
+
_(ENV!.each.to_a).must_equal [
|
411
|
+
['ONE', 1],
|
412
|
+
['A', 'A'],
|
413
|
+
['INT_HASH', { one: 1, two: 2 }],
|
414
|
+
['FLOAT', 1.234],
|
415
|
+
]
|
416
|
+
|
417
|
+
_(ENV!.to_enum.to_a).must_equal ENV!.to_a
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
describe "Hash-like read methods" do
|
422
|
+
before do
|
423
|
+
ENV['ONE'] = '1'
|
424
|
+
ENV['A'] = 'A'
|
425
|
+
ENV['INT_HASH'] = 'one: 1, two: 2'
|
426
|
+
ENV['FLOAT'] = '1.234'
|
427
|
+
|
428
|
+
ENV!.config do
|
429
|
+
use 'ONE', class: Integer
|
430
|
+
use 'A', class: String
|
431
|
+
use 'INT_HASH', class: Hash, of: Integer
|
432
|
+
use 'FLOAT', class: Float
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
it "implements .assoc and .rassoc correctly" do
|
437
|
+
_(ENV!.assoc('ONE')).must_equal ['ONE', 1]
|
438
|
+
_(ENV!.rassoc(1)).must_equal ['ONE', 1]
|
439
|
+
end
|
440
|
+
|
441
|
+
it "implements .each_key correctly" do
|
442
|
+
_(ENV!.each_key.to_a).must_equal(%w[ONE A INT_HASH FLOAT])
|
443
|
+
keys = []
|
444
|
+
ENV!.each_key do |key|
|
445
|
+
keys << key
|
446
|
+
end
|
447
|
+
_(keys).must_equal(%w[ONE A INT_HASH FLOAT])
|
448
|
+
end
|
449
|
+
|
450
|
+
it "implements .each_pair correctly" do
|
451
|
+
_(ENV!.each_pair.to_a).must_equal(ENV!.to_a)
|
452
|
+
pairs = []
|
453
|
+
ENV!.each_pair do |pair|
|
454
|
+
pairs << pair
|
455
|
+
end
|
456
|
+
_(pairs).must_equal(ENV!.to_a)
|
457
|
+
end
|
458
|
+
|
459
|
+
it "implements .each_value correctly" do
|
460
|
+
_(ENV!.each_value.to_a).must_equal [1, 'A', { one: 1, two: 2 }, 1.234]
|
461
|
+
values = []
|
462
|
+
ENV!.each_value do |value|
|
463
|
+
values << value
|
464
|
+
end
|
465
|
+
_(values).must_equal [1, 'A', { one: 1, two: 2 }, 1.234]
|
466
|
+
end
|
467
|
+
|
468
|
+
it "implements .empty? correctly" do
|
469
|
+
_(ENV!.empty?).must_equal(false)
|
470
|
+
end
|
471
|
+
|
472
|
+
it "implements .except correctly" do
|
473
|
+
_(ENV!.except('INT_HASH', 'FLOAT', 'NOTATHING')).must_equal({
|
474
|
+
'ONE' => 1,
|
475
|
+
'A' => 'A',
|
476
|
+
})
|
477
|
+
end
|
478
|
+
|
479
|
+
it "implements .fetch correctly" do
|
480
|
+
_(ENV!.fetch('ONE')).must_equal 1
|
481
|
+
_{
|
482
|
+
ENV!.fetch('TWO')
|
483
|
+
}.must_raise KeyError
|
484
|
+
_(ENV!.fetch('TWO', 2)).must_equal 2
|
485
|
+
_(ENV!.fetch('TWO') { 22 }).must_equal 22
|
486
|
+
end
|
487
|
+
|
488
|
+
it "implements .invert correctly" do
|
489
|
+
_(ENV!.invert).must_equal({
|
490
|
+
1 => 'ONE',
|
491
|
+
'A' => 'A',
|
492
|
+
{ one: 1, two: 2 } => 'INT_HASH',
|
493
|
+
1.234 => 'FLOAT',
|
494
|
+
})
|
495
|
+
end
|
496
|
+
|
497
|
+
it "implements .key correctly" do
|
498
|
+
_(ENV!.key(1)).must_equal 'ONE'
|
499
|
+
end
|
500
|
+
|
501
|
+
it "implements .key?/.has_key? correctly" do
|
502
|
+
_(ENV!.key?('ONE')).must_equal true
|
503
|
+
_(ENV!.has_key?('ONE')).must_equal true
|
504
|
+
|
505
|
+
_(ENV!.key?('TWO')).must_equal false
|
506
|
+
_(ENV!.has_key?('TWO')).must_equal false
|
507
|
+
end
|
508
|
+
|
509
|
+
it "implements .length correctly" do
|
510
|
+
_(ENV!.length).must_equal 4
|
511
|
+
_(ENV!.size).must_equal 4
|
512
|
+
end
|
513
|
+
|
514
|
+
it "implements .slice correctly" do
|
515
|
+
_(ENV!.slice('INT_HASH', 'FLOAT', 'NOTATHING')).must_equal({
|
516
|
+
'INT_HASH' => { one: 1, two: 2 },
|
517
|
+
'FLOAT' => 1.234,
|
518
|
+
})
|
519
|
+
end
|
520
|
+
|
521
|
+
it "implements .to_hash correctly" do
|
522
|
+
_(ENV!.to_hash).must_equal ENV!.to_h
|
523
|
+
end
|
524
|
+
|
525
|
+
it "implements .value?/has_value? correctly" do
|
526
|
+
_(ENV!.value?(1)).must_equal true
|
527
|
+
_(ENV!.value?(2)).must_equal false
|
528
|
+
_(ENV!.has_value?(1)).must_equal true
|
529
|
+
_(ENV!.has_value?(2)).must_equal false
|
530
|
+
end
|
531
|
+
|
532
|
+
it "implements .values_at correctly" do
|
533
|
+
_(ENV!.values_at('INT_HASH', 'FLOAT', 'NOTATHING')).must_equal [
|
534
|
+
{ one: 1, two: 2 }, 1.234, nil
|
535
|
+
]
|
536
|
+
end
|
537
|
+
end
|
369
538
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,13 +1,21 @@
|
|
1
|
-
require 'simplecov'
|
2
|
-
require 'coveralls'
|
3
|
-
|
4
1
|
require 'minitest/autorun'
|
5
2
|
require 'minitest/spec'
|
6
3
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
]
|
11
|
-
|
4
|
+
require 'simplecov'
|
5
|
+
|
6
|
+
SimpleCov.start 'rails' do
|
7
|
+
if ENV['CI']
|
8
|
+
require 'simplecov-lcov'
|
9
|
+
|
10
|
+
SimpleCov::Formatter::LcovFormatter.config do |c|
|
11
|
+
c.report_with_single_file = true
|
12
|
+
c.single_report_path = 'coverage/lcov.info'
|
13
|
+
end
|
14
|
+
|
15
|
+
formatter SimpleCov::Formatter::LcovFormatter
|
16
|
+
end
|
17
|
+
|
18
|
+
add_filter %w[version.rb initializer.rb]
|
19
|
+
end
|
12
20
|
|
13
21
|
require 'env_bang'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: env_bang
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.alpha.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Camenisch
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -46,8 +46,8 @@ executables: []
|
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
|
+
- ".circleci/config.yml"
|
49
50
|
- ".gitignore"
|
50
|
-
- ".travis.yml"
|
51
51
|
- Gemfile
|
52
52
|
- LICENSE.txt
|
53
53
|
- README.md
|