a9n 0.10.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,96 +0,0 @@
1
- require 'simplecov'
2
- SimpleCov.start
3
-
4
- require 'rubygems'
5
- require 'bundler/setup'
6
-
7
- require 'a9n'
8
- require 'pry'
9
-
10
- RSpec.configure do |config|
11
- # rspec-expectations config goes here. You can use an alternate
12
- # assertion/expectation library such as wrong or the stdlib/minitest
13
- # assertions if you prefer.
14
- config.expect_with :rspec do |expectations|
15
- # This option will default to `true` in RSpec 4. It makes the `description`
16
- # and `failure_message` of custom matchers include text for helper methods
17
- # defined using `chain`, e.g.:
18
- # be_bigger_than(2).and_smaller_than(4).description
19
- # # => 'be bigger than 2 and smaller than 4'
20
- # ...rather than:
21
- # # => 'be bigger than 2'
22
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
23
- end
24
-
25
- # rspec-mocks config goes here. You can use an alternate test double
26
- # library (such as bogus or mocha) by changing the `mock_with` option here.
27
- config.mock_with :rspec do |mocks|
28
- # Prevents you from mocking or stubbing a method that does not exist on
29
- # a real object. This is generally recommended, and will default to
30
- # `true` in RSpec 4.
31
- mocks.verify_partial_doubles = true
32
- end
33
-
34
- # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
35
- # have no way to turn it off -- the option exists only for backwards
36
- # compatibility in RSpec 3). It causes shared context metadata to be
37
- # inherited by the metadata hash of host groups and examples, rather than
38
- # triggering implicit auto-inclusion in groups with matching metadata.
39
- config.shared_context_metadata_behavior = :apply_to_host_groups
40
-
41
- # This allows you to limit a spec run to individual examples or groups
42
- # you care about by tagging them with `:focus` metadata. When nothing
43
- # is tagged with `:focus`, all examples get run. RSpec also provides
44
- # aliases for `it`, `describe`, and `context` that include `:focus`
45
- # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
46
- config.filter_run_when_matching :focus
47
-
48
- # Allows RSpec to persist some state between runs in order to support
49
- # the `--only-failures` and `--next-failure` CLI options. We recommend
50
- # you configure your source control system to ignore this file.
51
- config.example_status_persistence_file_path = 'spec/examples.txt'
52
-
53
- # Limits the available syntax to the non-monkey patched syntax that is
54
- # recommended. For more details, see:
55
- # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
56
- # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
- # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
58
- config.disable_monkey_patching!
59
-
60
- # This setting enables warnings. It's recommended, but in some cases may
61
- # be too noisy due to issues in dependencies.
62
- config.warnings = true
63
-
64
- # Many RSpec users commonly either run the entire suite or an individual
65
- # file, and it's useful to allow more verbose output when running an
66
- # individual spec file.
67
- # if config.files_to_run.one?
68
- # # Use the documentation formatter for detailed output,
69
- # # unless a formatter has already been configured
70
- # # (e.g. via a command-line flag).
71
- # config.default_formatter = 'doc'
72
- # end
73
-
74
- # Print the 10 slowest examples and example groups at the
75
- # end of the spec run, to help surface which specs are running
76
- # particularly slow.
77
- config.profile_examples = 10
78
-
79
- # Run specs in random order to surface order dependencies. If you find an
80
- # order dependency and want to debug it, you can fix the order by providing
81
- # the seed, which is printed after each run.
82
- # --seed 1234
83
- config.order = :random
84
-
85
- # Seed global randomization in this process using the `--seed` CLI option.
86
- # Setting this allows you to use `--seed` to deterministically reproduce
87
- # test failures related to randomization by passing the same `--seed` value
88
- # as the one that triggered the failure.
89
- Kernel.srand config.seed
90
- end
91
-
92
- def clean_singleton(klass)
93
- [:@storage, :@env, :@app, :@root].each do |var|
94
- klass.instance_variable_defined?(var) && klass.remove_instance_variable(var)
95
- end
96
- end
@@ -1,268 +0,0 @@
1
- RSpec.describe A9n do
2
- subject { described_class }
3
- before { clean_singleton(subject) }
4
- after { clean_singleton(subject) }
5
-
6
- describe '.env' do
7
- before do
8
- subject.instance_variable_set(:@env, nil)
9
- end
10
-
11
- context 'app_env is set' do
12
- let(:app) { OpenStruct.new(env: ::A9n::StringInquirer.new('foo_env')) }
13
-
14
- before do
15
- allow(subject).to receive(:app).and_return(app)
16
- expect(subject).to receive(:env_var).never
17
- end
18
-
19
- it do
20
- expect(subject.env).to eq('foo_env')
21
- expect(subject.env.foo_env?).to eq(true)
22
- expect(subject.env.production?).to eq(false)
23
- end
24
- end
25
-
26
- context 'when APP_ENV is set' do
27
- before do
28
- expect(subject).to receive(:app_env).and_return(nil)
29
- expect(subject).to receive(:env_var).with('RAILS_ENV').and_return(nil)
30
- expect(subject).to receive(:env_var).with('RACK_ENV').and_return(nil)
31
- expect(subject).to receive(:env_var).with('APP_ENV').and_return('foo_env')
32
- end
33
-
34
- it do
35
- expect(subject.env).to eq('foo_env')
36
- expect(subject.env.foo_env?).to eq(true)
37
- expect(subject.env.production?).to eq(false)
38
- end
39
- end
40
-
41
- context 'unknown env' do
42
- before do
43
- expect(subject).to receive(:app_env).and_return(nil)
44
- expect(subject).to receive(:env_var).with('RAILS_ENV').and_return(nil)
45
- expect(subject).to receive(:env_var).with('RACK_ENV').and_return(nil)
46
- expect(subject).to receive(:env_var).with('APP_ENV').and_return(nil)
47
- end
48
-
49
- it do
50
- expect { subject.env }.to raise_error(A9n::UnknownEnvError)
51
- end
52
- end
53
- end
54
-
55
- describe '.groups' do
56
- before do
57
- subject.env = 'development'
58
- end
59
-
60
- it do
61
- expect(subject.groups).to eq(%w[default development])
62
- expect(subject.groups).to be_frozen
63
- end
64
- end
65
-
66
- describe '.app' do
67
- context 'when rails not found' do
68
- before do
69
- expect(subject).to receive(:rails_app).and_return(nil)
70
- end
71
-
72
- it do
73
- expect(subject.app).to be_nil
74
- end
75
- end
76
-
77
- context 'when rails app is being used' do
78
- let(:app) { double(env: 'test', root: '/apps/a9n') }
79
-
80
- before do
81
- expect(subject).to receive(:rails_app).and_return(app)
82
- end
83
-
84
- it do
85
- expect(subject.app).to eq(app)
86
- end
87
- end
88
-
89
- context 'when custom non-rails app is being used' do
90
- let(:app) { double(env: 'test', root: '/apps/a9n') }
91
-
92
- before do
93
- subject.app = app
94
- end
95
-
96
- it do
97
- expect(subject.app).to eq(app)
98
- end
99
- end
100
- end
101
-
102
- describe '.root' do
103
- context 'when app is set' do
104
- let(:app) { OpenStruct.new(env: 'test', root: '/apps/a9n') }
105
-
106
- before do
107
- subject.app = app
108
- end
109
-
110
- context 'with custom path' do
111
- before do
112
- subject.root = '/home/knapo/workspace/a9n'
113
- end
114
-
115
- it do
116
- expect(subject.root).to eq(Pathname.new('/home/knapo/workspace/a9n'))
117
- expect(subject.root).to be_frozen
118
- end
119
- end
120
-
121
- context 'with local app path' do
122
- it do
123
- expect(subject.root).to eq('/apps/a9n')
124
- end
125
- end
126
- end
127
-
128
- context 'when app is not set' do
129
- it do
130
- expect(subject.root).to eq(A9n.root_from_bundle_env)
131
- end
132
-
133
- context 'when setting a custom path' do
134
- before do
135
- subject.root = '/home/knapo/workspace/a9n'
136
- end
137
-
138
- it do
139
- expect(subject.root).to eq(Pathname.new('/home/knapo/workspace/a9n'))
140
- end
141
- end
142
- end
143
- end
144
-
145
- describe '.rails_app' do
146
- context 'when defined' do
147
- before do
148
- Object.const_set(:Rails, Module.new)
149
- end
150
-
151
- after do
152
- Object.send(:remove_const, :Rails)
153
- end
154
-
155
- it do
156
- expect(subject.rails_app).to be_kind_of(Module)
157
- end
158
- end
159
-
160
- context 'when not defined' do
161
- it do
162
- expect(subject.rails_app).to be_nil
163
- end
164
- end
165
- end
166
-
167
- describe '.env_var' do
168
- before do
169
- ENV['FOO'] = 'little foo'
170
- end
171
-
172
- it do
173
- expect(subject.env_var('FOO')).to eq('little foo')
174
- expect(subject.env_var('FOO')).to be_frozen
175
- end
176
-
177
- it do
178
- expect(subject.env_var('IS_FOO')).to be_nil
179
- end
180
- end
181
-
182
- describe '.default_files' do
183
- before do
184
- subject.root = File.expand_path('../../test_app', __dir__)
185
- end
186
-
187
- it do
188
- expect(subject.default_files[0]).to include('a9n.yml')
189
- expect(Pathname.new(subject.default_files[0])).to be_absolute
190
- expect(subject.default_files[1]).to include('a9n/aws.yml')
191
- expect(Pathname.new(subject.default_files[1])).to be_absolute
192
- end
193
- end
194
-
195
- describe '.load' do
196
- before do
197
- expect(described_class).to receive(:env).exactly(2).times.and_return('dev')
198
- subject.root = '/apps/test_app'
199
- files.each do |f, cfg|
200
- expect(A9n::Loader).to receive(:new).with(f, kind_of(A9n::Scope), 'dev').and_return(double(get: cfg))
201
- end
202
- end
203
-
204
- context 'when no files given' do
205
- let(:files) do
206
- {
207
- '/apps/test_app/config/file1.yml' => { host: 'host1.com' },
208
- '/apps/test_app/config/dir/file2.yml' => { host: 'host2.com' }
209
- }
210
- end
211
-
212
- before do
213
- expect(subject).to receive(:default_files).and_return(files.keys)
214
- expect(subject).to receive(:absolute_paths_for).never
215
- end
216
-
217
- it do
218
- expect(subject.load).to eq(files.values)
219
- end
220
- end
221
-
222
- context 'when custom files given' do
223
- let(:given_files) do
224
- ['file3.yml', '/apps/test_app/config/dir/file4.yml']
225
- end
226
-
227
- let(:files) do
228
- {
229
- '/apps/test_app/config/file3.yml' => { host: 'host3.com' },
230
- '/apps/test_app/config/dir/file4.yml' => { host: 'host4.com' }
231
- }
232
- end
233
-
234
- before do
235
- expect(subject).to receive(:default_files).never
236
- expect(subject).to receive(:absolute_paths_for).with(given_files).and_call_original
237
- end
238
-
239
- it do
240
- expect(subject.load(*given_files)).to eq(files.values)
241
- end
242
- end
243
- end
244
-
245
- describe '.method_missing' do
246
- context 'when storage is empty' do
247
- before do
248
- expect(subject).to receive(:load).once
249
- end
250
-
251
- it do
252
- expect(subject.storage).to be_empty
253
- expect { subject.whatever }.to raise_error(A9n::NoSuchConfigurationVariableError)
254
- end
255
- end
256
-
257
- context 'when storage is not empty' do
258
- before do
259
- subject.storage[:whenever] = 'whenever'
260
- expect(subject).not_to receive(:load)
261
- end
262
-
263
- it do
264
- expect { subject.whatever }.to raise_error(A9n::NoSuchConfigurationVariableError)
265
- end
266
- end
267
- end
268
- end
@@ -1,207 +0,0 @@
1
- RSpec.describe A9n::Loader do
2
- let(:scope) { A9n::Scope.new('a9n') }
3
- let(:env) { 'test' }
4
- let(:root) { File.expand_path('../../test_app', __dir__) }
5
- let(:file_path) { File.join(root, 'config/a9n.yml') }
6
- subject { described_class.new(file_path, scope, env) }
7
-
8
- describe '#intialize' do
9
- it { expect(subject.scope).to eq(scope) }
10
- it { expect(subject.env).to eq(env) }
11
- it { expect(subject.local_file).to eq(file_path) }
12
- it { expect(subject.example_file).to eq("#{file_path}.example") }
13
- end
14
-
15
- describe '#load' do
16
- let(:example_config) do
17
- { app_url: 'http://127.0.0.1:3000', api_key: 'example1234' }
18
- end
19
-
20
- let(:local_config) do
21
- { app_host: '127.0.0.1:3000', api_key: 'local1234' }
22
- end
23
-
24
- let(:env) { 'tropical' }
25
- let(:config) { subject.get }
26
-
27
- context 'when no configuration file exists' do
28
- before do
29
- expect(described_class).to receive(:load_yml).with(subject.example_file, scope, env).and_return(nil)
30
- expect(described_class).to receive(:load_yml).with(subject.local_file, scope, env).and_return(nil)
31
- end
32
-
33
- it 'raises expection' do
34
- expect {
35
- subject.load
36
- }.to raise_error(A9n::MissingConfigurationDataError)
37
- end
38
- end
39
-
40
- context 'when only example configuration file exists' do
41
- before do
42
- expect(described_class).to receive(:load_yml).with(subject.example_file, scope, env).and_return(example_config)
43
- expect(described_class).to receive(:load_yml).with(subject.local_file, scope, env).and_return(nil)
44
- subject.load
45
- end
46
-
47
- it { expect(config.app_url).to eq('http://127.0.0.1:3000') }
48
- it { expect(config.api_key).to eq('example1234') }
49
-
50
- it do
51
- expect { config.app_host }.to raise_error(A9n::NoSuchConfigurationVariableError)
52
- end
53
- end
54
-
55
- context 'when only local configuration file exists' do
56
- before do
57
- expect(described_class).to receive(:load_yml).with(subject.example_file, scope, env).and_return(nil)
58
- expect(described_class).to receive(:load_yml).with(subject.local_file, scope, env).and_return(local_config)
59
- subject.load
60
- end
61
-
62
- it { expect(config.app_host).to eq('127.0.0.1:3000') }
63
- it { expect(config.api_key).to eq('local1234') }
64
-
65
- it do
66
- expect { config.app_url }.to raise_error(A9n::NoSuchConfigurationVariableError)
67
- end
68
- end
69
-
70
- context 'when both local and base configuration file exists without defaults' do
71
- context 'with same data' do
72
- before do
73
- expect(described_class).to receive(:load_yml).with(subject.example_file, scope, env).and_return(example_config)
74
- expect(described_class).to receive(:load_yml).with(subject.local_file, scope, env).and_return(example_config)
75
- subject.load
76
- end
77
-
78
- it { expect(config.app_url).to eq('http://127.0.0.1:3000') }
79
- it { expect(config.api_key).to eq('example1234') }
80
-
81
- it do
82
- expect { config.app_host }.to raise_error(A9n::NoSuchConfigurationVariableError)
83
- end
84
- end
85
-
86
- context 'with different data' do
87
- before do
88
- expect(described_class).to receive(:load_yml).with(subject.example_file, scope, env).and_return(example_config)
89
- expect(described_class).to receive(:load_yml).with(subject.local_file, scope, env).and_return(local_config)
90
- end
91
-
92
- let(:missing_variables_names) { example_config.keys - local_config.keys }
93
-
94
- it 'raises expection with missing variables names' do
95
- expect {
96
- subject.load
97
- }.to raise_error(A9n::MissingConfigurationVariablesError, /#{missing_variables_names.join(', ')}/)
98
- end
99
- end
100
- end
101
- end
102
-
103
- describe '.load_yml' do
104
- let(:env) { 'test' }
105
- subject { described_class.load_yml(file_path, scope, env) }
106
-
107
- context 'when file not exists' do
108
- let(:file_path) { 'file_not_existing_in_the_universe.yml' }
109
-
110
- it { expect(subject).to be_nil }
111
- end
112
-
113
- context 'when file exists' do
114
- shared_examples 'non-empty config file' do
115
- it 'returns non-empty hash' do
116
- expect(subject).to be_kind_of(Hash)
117
- expect(subject).to be_frozen
118
- expect(subject.keys).to_not be_empty
119
- end
120
- end
121
-
122
- before do
123
- ENV['ERB_FOO'] = 'erbized foo'
124
- ENV['FOO_PASSWORD'] = 'foo123'
125
- ENV['FOO_KEY'] = 'key123'
126
- end
127
-
128
- after do
129
- ENV.delete('ERB_FOO')
130
- ENV.delete('FOO_PASSWORD')
131
- ENV.delete('FOO_KEY')
132
- end
133
-
134
- context 'when file has erb extension' do
135
- let(:file_path) { File.join(root, 'config/a9n/cloud.yml.erb') }
136
-
137
- it_behaves_like 'non-empty config file'
138
- end
139
-
140
- context 'having env and defaults data' do
141
- let(:file_path) { File.join(root, 'config/a9n.yml') }
142
-
143
- it_behaves_like 'non-empty config file'
144
-
145
- it 'contains only frozen values' do
146
- expect(subject.values.reject(&:frozen?)).to eq([])
147
- end
148
-
149
- it 'contains keys from defaults scope' do
150
- expect(subject[:default_foo]).to eq('default foo')
151
- expect(subject[:overriden_foo]).to eq('already overriden foo')
152
- end
153
-
154
- it 'has symbolized keys' do
155
- expect(subject.keys.first).to be_kind_of(Symbol)
156
- expect(subject[:hash_foo]).to be_kind_of(Hash)
157
- expect(subject[:hash_foo].keys.first).to be_kind_of(Symbol)
158
- expect(subject[:hash_foo]).to eq(foo_1: 'hello 1', foo_2: 'hello 2', foo_key: 'key123')
159
- end
160
-
161
- it 'parses erb' do
162
- expect(subject[:erb_foo]).to eq('erbized foo')
163
- end
164
-
165
- it 'gets valus from ENV' do
166
- expect(subject[:foo_password]).to eq('foo123')
167
- end
168
-
169
- it 'raises exception when ENV var is not set' do
170
- ENV.delete('FOO_PASSWORD')
171
- expect { subject[:foo_password] }.to raise_error(A9n::MissingEnvVariableError)
172
- end
173
-
174
- it 'raises exception when ENV var is set to nil' do
175
- ENV['FOO_PASSWORD'] = nil
176
- expect { subject[:foo_password] }.to raise_error(A9n::MissingEnvVariableError)
177
- end
178
- end
179
-
180
- context 'having no env and only defaults data' do
181
- let(:file_path) { File.join(root, 'config/a9n.yml') }
182
- let(:env) { 'production' }
183
-
184
- it_behaves_like 'non-empty config file'
185
-
186
- it 'contains keys from defaults scope' do
187
- expect(subject[:default_foo]).to eq('default foo')
188
- expect(subject[:overriden_foo]).to eq('not yet overriden foo')
189
- end
190
- end
191
-
192
- context 'having only env and no default data' do
193
- let(:file_path) { File.join(root, 'config/no_defaults.yml') }
194
-
195
- context 'valid env' do
196
- let(:env) { 'production' }
197
- it_behaves_like 'non-empty config file'
198
- end
199
-
200
- context 'invalid env' do
201
- let(:env) { 'tropical' }
202
- it { expect(subject).to be_nil }
203
- end
204
- end
205
- end
206
- end
207
- end