mixlib-config 2.2.11 → 3.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mixlib/config.rb +65 -44
- data/lib/mixlib/config/configurable.rb +40 -23
- data/lib/mixlib/config/version.rb +1 -1
- metadata +7 -72
- data/Gemfile +0 -3
- data/README.md +0 -304
- data/Rakefile +0 -32
- data/mixlib-config.gemspec +0 -32
- data/spec/mixlib/config_spec.rb +0 -1273
- data/spec/spec_helper.rb +0 -15
data/Gemfile
DELETED
data/README.md
DELETED
@@ -1,304 +0,0 @@
|
|
1
|
-
# Mixlib::Config
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.org/chef/mixlib-config.svg?branch=master)](https://travis-ci.org/chef/mixlib-config)[![Gem Version](https://badge.fury.io/rb/mixlib-config.svg)](https://badge.fury.io/rb/mixlib-config)
|
4
|
-
|
5
|
-
Mixlib::Config provides a class-based configuration object, as used in Chef. To use in your project:
|
6
|
-
|
7
|
-
```ruby
|
8
|
-
require 'mixlib/config'
|
9
|
-
|
10
|
-
module MyConfig
|
11
|
-
extend Mixlib::Config
|
12
|
-
config_strict_mode true
|
13
|
-
default :first_value, 'something'
|
14
|
-
default :other_value, 'something_else'
|
15
|
-
end
|
16
|
-
```
|
17
|
-
|
18
|
-
You can use this to provide a configuration file for a user. For example, if you do this:
|
19
|
-
|
20
|
-
```ruby
|
21
|
-
MyConfig.from_file('~/.myconfig.rb')
|
22
|
-
```
|
23
|
-
|
24
|
-
A user could write a Ruby config file that looked like this:
|
25
|
-
|
26
|
-
```ruby
|
27
|
-
first_value 'hi'
|
28
|
-
second_value "#{first_value}! 10 times 10 is #{10*10}!"
|
29
|
-
```
|
30
|
-
|
31
|
-
Inside your app, you can check configuration values with this syntax:
|
32
|
-
|
33
|
-
```ruby
|
34
|
-
MyConfig.first_value # returns 'something'
|
35
|
-
MyConfig[:first_value] # returns 'something'
|
36
|
-
```
|
37
|
-
|
38
|
-
And you can modify configuration values with this syntax:
|
39
|
-
|
40
|
-
```ruby
|
41
|
-
MyConfig.first_value('foobar') # sets first_value to 'foobar'
|
42
|
-
MyConfig.first_value = 'foobar' # sets first_value to 'foobar'
|
43
|
-
MyConfig[:first_value] = 'foobar' # sets first_value to 'foobar'
|
44
|
-
```
|
45
|
-
|
46
|
-
If you prefer to allow your users to pass in configuration via YAML, JSON or TOML files, `mixlib-config` supports that too!
|
47
|
-
|
48
|
-
```ruby
|
49
|
-
MyConfig.from_file('~/.myconfig.yml')
|
50
|
-
MyConfig.from_file('~/.myconfig.json')
|
51
|
-
MyConfig.from_file('~/.myconfig.toml')
|
52
|
-
```
|
53
|
-
|
54
|
-
This way, a user could write a YAML config file that looked like this:
|
55
|
-
|
56
|
-
```yaml
|
57
|
-
---
|
58
|
-
first_value: 'hi'
|
59
|
-
second_value: 'goodbye'
|
60
|
-
```
|
61
|
-
|
62
|
-
or a JSON file that looks like this:
|
63
|
-
|
64
|
-
```json
|
65
|
-
{
|
66
|
-
"first_value": "hi",
|
67
|
-
"second_value": "goodbye"
|
68
|
-
}
|
69
|
-
```
|
70
|
-
|
71
|
-
or a TOML file that looks like this:
|
72
|
-
|
73
|
-
```toml
|
74
|
-
first_value = "hi"
|
75
|
-
second_value = "goodbye"
|
76
|
-
```
|
77
|
-
|
78
|
-
Please note: There is an inherent limitation in the logic you can do with YAML and JSON file. At this time, `mixlib-config` does not support ERB or other logic in YAML or JSON config (read "static content only").
|
79
|
-
|
80
|
-
## Nested Configuration
|
81
|
-
|
82
|
-
Often you want to be able to group configuration options to provide a common context. Mixlib::Config supports this thus:
|
83
|
-
|
84
|
-
```ruby
|
85
|
-
require 'mixlib/config'
|
86
|
-
|
87
|
-
module MyConfig
|
88
|
-
extend Mixlib::Config
|
89
|
-
config_context :logging do
|
90
|
-
default :base_filename, 'mylog'
|
91
|
-
default :max_log_files, 10
|
92
|
-
end
|
93
|
-
end
|
94
|
-
```
|
95
|
-
|
96
|
-
The user can write their config file in one of three formats:
|
97
|
-
|
98
|
-
### Method Style
|
99
|
-
|
100
|
-
```ruby
|
101
|
-
logging.base_filename 'superlog'
|
102
|
-
logging.max_log_files 2
|
103
|
-
```
|
104
|
-
|
105
|
-
### Block Style
|
106
|
-
|
107
|
-
Using this format the block is executed in the context, so all configurables on that context is directly accessible
|
108
|
-
|
109
|
-
```ruby
|
110
|
-
logging do
|
111
|
-
base_filename 'superlog'
|
112
|
-
max_log_files 2
|
113
|
-
end
|
114
|
-
```
|
115
|
-
|
116
|
-
### Block with Argument Style
|
117
|
-
|
118
|
-
Using this format the context is given to the block as an argument
|
119
|
-
|
120
|
-
```ruby
|
121
|
-
logging do |l|
|
122
|
-
l.base_filename = 'superlog'
|
123
|
-
l.max_log_files = 2
|
124
|
-
end
|
125
|
-
```
|
126
|
-
|
127
|
-
You can access these variables thus:
|
128
|
-
|
129
|
-
```ruby
|
130
|
-
MyConfig.logging.base_filename
|
131
|
-
MyConfig[:logging][:max_log_files]
|
132
|
-
```
|
133
|
-
|
134
|
-
### Lists of Contexts
|
135
|
-
For use cases where you need to be able to specify a list of things with identical configuration
|
136
|
-
you can define a `context_config_list` like so:
|
137
|
-
|
138
|
-
```ruby
|
139
|
-
require 'mixlib/config'
|
140
|
-
|
141
|
-
module MyConfig
|
142
|
-
extend Mixlib::Config
|
143
|
-
|
144
|
-
# The first argument is the plural word for your item, the second is the singular
|
145
|
-
config_context_list :apples, :apple do
|
146
|
-
default :species
|
147
|
-
default :color, 'red'
|
148
|
-
default :crispness, 10
|
149
|
-
end
|
150
|
-
end
|
151
|
-
```
|
152
|
-
|
153
|
-
With this definition everytime the `apple` is called within the config file it
|
154
|
-
will create a new item that can be configured with a block like so:
|
155
|
-
|
156
|
-
```ruby
|
157
|
-
apple do
|
158
|
-
species 'Royal Gala'
|
159
|
-
end
|
160
|
-
apple do
|
161
|
-
species 'Granny Smith'
|
162
|
-
color 'green'
|
163
|
-
end
|
164
|
-
```
|
165
|
-
|
166
|
-
You can then iterate over the defined values in code:
|
167
|
-
|
168
|
-
```ruby
|
169
|
-
MyConfig.apples.each do |apple|
|
170
|
-
puts "#{apple.species} are #{apple.color}"
|
171
|
-
end
|
172
|
-
|
173
|
-
# => Royal Gala are red
|
174
|
-
# => Granny Smith are green
|
175
|
-
```
|
176
|
-
|
177
|
-
_**Note**: When using the config context lists they must use the [block style](#block-style) or [block with argument style](#block-with-argument-style)_
|
178
|
-
|
179
|
-
### Hashes of Contexts
|
180
|
-
For use cases where you need to be able to specify a list of things with identical configuration
|
181
|
-
that are keyed to a specific value, you can define a `context_config_hash` like so:
|
182
|
-
|
183
|
-
```ruby
|
184
|
-
require 'mixlib/config'
|
185
|
-
|
186
|
-
module MyConfig
|
187
|
-
extend Mixlib::Config
|
188
|
-
|
189
|
-
# The first argument is the plural word for your item, the second is the singular
|
190
|
-
config_context_hash :apples, :apple do
|
191
|
-
default :species
|
192
|
-
default :color, 'red'
|
193
|
-
default :crispness, 10
|
194
|
-
end
|
195
|
-
end
|
196
|
-
```
|
197
|
-
|
198
|
-
This can then be used in the config file like so:
|
199
|
-
|
200
|
-
```ruby
|
201
|
-
apple 'Royal Gala' do
|
202
|
-
species 'Royal Gala'
|
203
|
-
end
|
204
|
-
apple 'Granny Smith' do
|
205
|
-
species 'Granny Smith'
|
206
|
-
color 'green'
|
207
|
-
end
|
208
|
-
|
209
|
-
# You can also reopen a context to edit a value
|
210
|
-
apple 'Royal Gala' do
|
211
|
-
crispness 3
|
212
|
-
end
|
213
|
-
```
|
214
|
-
|
215
|
-
You can then iterate over the defined values in code:
|
216
|
-
|
217
|
-
```ruby
|
218
|
-
MyConfig.apples.each do |key, apple|
|
219
|
-
puts "#{key} => #{apple.species} are #{apple.color}"
|
220
|
-
end
|
221
|
-
|
222
|
-
# => Royal Gala => Royal Gala are red
|
223
|
-
# => Granny Smith => Granny Smith are green
|
224
|
-
```
|
225
|
-
|
226
|
-
_**Note**: When using the config context hashes they must use the [block style](#block-style) or [block with argument style](#block-with-argument-style)_
|
227
|
-
|
228
|
-
## Default Values
|
229
|
-
|
230
|
-
Mixlib::Config has a powerful default value facility. In addition to being able to specify explicit default values, you can even specify Ruby code blocks that will run if the config value is not set. This can allow you to build options whose values are based on other options.
|
231
|
-
|
232
|
-
```ruby
|
233
|
-
require 'mixlib/config'
|
234
|
-
|
235
|
-
module MyConfig
|
236
|
-
extend Mixlib::Config
|
237
|
-
config_strict_mode true
|
238
|
-
default :verbosity, 1
|
239
|
-
default(:print_network_requests) { verbosity >= 2 }
|
240
|
-
default(:print_ridiculously_unimportant_stuff) { verbosity >= 10 }
|
241
|
-
end
|
242
|
-
```
|
243
|
-
|
244
|
-
This allows the user to quickly specify a number of values with one default, while still allowing them to override anything:
|
245
|
-
|
246
|
-
```ruby
|
247
|
-
verbosity 5
|
248
|
-
print_network_requests false
|
249
|
-
```
|
250
|
-
|
251
|
-
## Strict Mode
|
252
|
-
|
253
|
-
Misspellings are a common configuration problem, and Mixlib::Config has an answer: `config_strict_mode`. Setting `config_strict_mode` to `true` will cause any misspelled or incorrect configuration option references to throw `Mixlib::Config::UnknownConfigOptionError`.
|
254
|
-
|
255
|
-
```ruby
|
256
|
-
require 'mixlib/config'
|
257
|
-
|
258
|
-
module MyConfig
|
259
|
-
extend Mixlib::Config
|
260
|
-
config_strict_mode true
|
261
|
-
default :filename, '~/output.txt'
|
262
|
-
configurable :server_url # configurable declares an option with no default value
|
263
|
-
config_context :logging do
|
264
|
-
default :base_name, 'log'
|
265
|
-
default :max_files, 20
|
266
|
-
end
|
267
|
-
end
|
268
|
-
```
|
269
|
-
|
270
|
-
Now if a user types `fielname "~/output-mine.txt"` in their configuration file, it will toss an exception telling them that the option "fielname" is unknown. If you do not set config_strict_mode, the fielname option will be merrily set and the application just won't know about it.
|
271
|
-
|
272
|
-
Different config_contexts can have different strict modes; but they inherit the strict mode of their parent if you don't explicitly set it. So setting it once at the top level is sufficient. In the above example, `logging.base_naem 'mylog'` will raise an error.
|
273
|
-
|
274
|
-
In conclusion: _always set config_strict_mode to true_. You know you want to.
|
275
|
-
|
276
|
-
## Testing and Reset
|
277
|
-
|
278
|
-
Testing your application with different sets of arguments can by simplified with `reset`. Call `MyConfig.reset` before each test and all configuration will be reset to its default value. There's no need to explicitly unset all your options between each run.
|
279
|
-
|
280
|
-
NOTE: if you have arrays of arrays, or other deep nesting, we suggest you use code blocks to set up your default values (`default(:option) { [ [ 1, 2 ], [ 3, 4 ] ] }`). Deep children will not always be reset to their default values.
|
281
|
-
|
282
|
-
Enjoy!
|
283
|
-
|
284
|
-
## Contributing
|
285
|
-
|
286
|
-
For information on contributing to this project see <https://github.com/chef/chef/blob/master/CONTRIBUTING.md>
|
287
|
-
|
288
|
-
## License
|
289
|
-
|
290
|
-
- Copyright:: Copyright (c) 2009-2016 Chef Software, Inc.
|
291
|
-
- License:: Apache License, Version 2.0
|
292
|
-
|
293
|
-
```text
|
294
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
295
|
-
you may not use this file except in compliance with the License.
|
296
|
-
You may obtain a copy of the License at
|
297
|
-
|
298
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
299
|
-
|
300
|
-
Unless required by applicable law or agreed to in writing, software
|
301
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
302
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
303
|
-
See the License for the specific language governing permissions and
|
304
|
-
limitations under the License.
|
data/Rakefile
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require "bundler"
|
2
|
-
require "rubygems"
|
3
|
-
require "rubygems/package_task"
|
4
|
-
require "rdoc/task"
|
5
|
-
require "rspec/core/rake_task"
|
6
|
-
require "mixlib/config/version"
|
7
|
-
|
8
|
-
Bundler::GemHelper.install_tasks
|
9
|
-
|
10
|
-
task default: [:style, :spec]
|
11
|
-
|
12
|
-
desc "Run specs"
|
13
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
14
|
-
spec.pattern = "spec/**/*_spec.rb"
|
15
|
-
end
|
16
|
-
|
17
|
-
begin
|
18
|
-
require "chefstyle"
|
19
|
-
require "rubocop/rake_task"
|
20
|
-
RuboCop::RakeTask.new(:style) do |task|
|
21
|
-
task.options += ["--display-cop-names", "--no-color"]
|
22
|
-
end
|
23
|
-
rescue LoadError
|
24
|
-
puts "chefstyle/rubocop is not available. gem install chefstyle to do style checking."
|
25
|
-
end
|
26
|
-
|
27
|
-
RDoc::Task.new do |rdoc|
|
28
|
-
rdoc.rdoc_dir = "rdoc"
|
29
|
-
rdoc.title = "mixlib-config #{Mixlib::Config::VERSION}"
|
30
|
-
rdoc.rdoc_files.include("README*")
|
31
|
-
rdoc.rdoc_files.include("lib/**/*.rb")
|
32
|
-
end
|
data/mixlib-config.gemspec
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
$:.unshift(File.dirname(__FILE__) + "/lib")
|
4
|
-
require "mixlib/config/version"
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = "mixlib-config"
|
8
|
-
s.version = Mixlib::Config::VERSION
|
9
|
-
|
10
|
-
s.authors = ["Chef Software, Inc."]
|
11
|
-
s.email = "legal@chef.io"
|
12
|
-
s.extra_rdoc_files = [
|
13
|
-
"LICENSE",
|
14
|
-
"README.md",
|
15
|
-
]
|
16
|
-
s.files = ["LICENSE", "NOTICE", "README.md", "Gemfile", "Rakefile"] + Dir.glob("*.gemspec") +
|
17
|
-
Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
18
|
-
s.homepage = "https://www.chef.io"
|
19
|
-
s.require_paths = ["lib"]
|
20
|
-
s.rubygems_version = "1.8.23"
|
21
|
-
s.required_ruby_version = ">= 2.2"
|
22
|
-
s.summary = "A class based configuration library"
|
23
|
-
s.description = s.summary
|
24
|
-
s.license = "Apache-2.0"
|
25
|
-
|
26
|
-
s.add_dependency "tomlrb"
|
27
|
-
|
28
|
-
s.add_development_dependency "rake"
|
29
|
-
s.add_development_dependency "rspec", "~> 3.0"
|
30
|
-
s.add_development_dependency "chefstyle"
|
31
|
-
s.add_development_dependency "rdoc"
|
32
|
-
end
|
data/spec/mixlib/config_spec.rb
DELETED
@@ -1,1273 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Author:: Adam Jacob (<adam@chef.io>)
|
3
|
-
# Copyright:: Copyright (c) 2008-2018, Chef Software Inc.
|
4
|
-
# License:: Apache License, Version 2.0
|
5
|
-
#
|
6
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
-
# you may not use this file except in compliance with the License.
|
8
|
-
# You may obtain a copy of the License at
|
9
|
-
#
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
|
20
|
-
|
21
|
-
describe Mixlib::Config do
|
22
|
-
before(:each) do
|
23
|
-
ConfigIt.configure do |c|
|
24
|
-
c[:alpha] = "omega"
|
25
|
-
c[:foo] = nil
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
it "loads a config file" do
|
30
|
-
allow(File).to receive(:exists?).and_return(true)
|
31
|
-
allow(File).to receive(:readable?).and_return(true)
|
32
|
-
allow(IO).to receive(:read).with("config.rb").and_return("alpha = 'omega'\nfoo = 'bar'")
|
33
|
-
expect(lambda do
|
34
|
-
ConfigIt.from_file("config.rb")
|
35
|
-
end).to_not raise_error
|
36
|
-
end
|
37
|
-
|
38
|
-
it "doesn't raise an ArgumentError with an explanation if you try and set a non-existent variable" do
|
39
|
-
expect(lambda do
|
40
|
-
ConfigIt[:foobar] = "blah"
|
41
|
-
end).to_not raise_error
|
42
|
-
end
|
43
|
-
|
44
|
-
it "raises an Errno::ENOENT if it can't find the file" do
|
45
|
-
expect(lambda do
|
46
|
-
ConfigIt.from_file("/tmp/timmytimmytimmy")
|
47
|
-
end).to raise_error(Errno::ENOENT)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "allows the error to bubble up when it's anything other than IOError" do
|
51
|
-
allow(IO).to receive(:read).with("config.rb").and_return("@#asdf")
|
52
|
-
expect(lambda do
|
53
|
-
ConfigIt.from_file("config.rb")
|
54
|
-
end).to raise_error(SyntaxError)
|
55
|
-
end
|
56
|
-
|
57
|
-
it "allows you to reference a value by index" do
|
58
|
-
expect(ConfigIt[:alpha]).to eql("omega")
|
59
|
-
end
|
60
|
-
|
61
|
-
it "allows you to reference a value by string index" do
|
62
|
-
expect(ConfigIt["alpha"]).to eql("omega")
|
63
|
-
end
|
64
|
-
|
65
|
-
it "allows you to set a value by index" do
|
66
|
-
ConfigIt[:alpha] = "one"
|
67
|
-
expect(ConfigIt[:alpha]).to eql("one")
|
68
|
-
end
|
69
|
-
|
70
|
-
it "allows you to set a value by string index" do
|
71
|
-
ConfigIt["alpha"] = "one"
|
72
|
-
expect(ConfigIt[:alpha]).to eql("one")
|
73
|
-
end
|
74
|
-
|
75
|
-
it "allows setting a value with attribute form" do
|
76
|
-
ConfigIt.arbitrary_value = 50
|
77
|
-
expect(ConfigIt.arbitrary_value).to eql(50)
|
78
|
-
expect(ConfigIt[:arbitrary_value]).to eql(50)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "allows setting a value with method form" do
|
82
|
-
ConfigIt.arbitrary_value 50
|
83
|
-
expect(ConfigIt.arbitrary_value).to eql(50)
|
84
|
-
expect(ConfigIt[:arbitrary_value]).to eql(50)
|
85
|
-
end
|
86
|
-
|
87
|
-
describe "when strict mode is on" do
|
88
|
-
class StrictClass
|
89
|
-
extend ::Mixlib::Config
|
90
|
-
config_strict_mode true
|
91
|
-
default :x, 1
|
92
|
-
end
|
93
|
-
|
94
|
-
it "allows you to get and set configured values" do
|
95
|
-
StrictClass.x = StrictClass.x * 2
|
96
|
-
StrictClass[:x] = StrictClass[:x] * 2
|
97
|
-
end
|
98
|
-
|
99
|
-
it "raises an error when you get an arbitrary config option with .y" do
|
100
|
-
expect(lambda { StrictClass.y }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Reading unsupported config value y.")
|
101
|
-
end
|
102
|
-
|
103
|
-
it "raises an error when you get an arbitrary config option with [:y]" do
|
104
|
-
expect(lambda { StrictClass[:y] }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Reading unsupported config value y.")
|
105
|
-
end
|
106
|
-
|
107
|
-
it "raises an error when you set an arbitrary config option with .y = 10" do
|
108
|
-
expect(lambda { StrictClass.y = 10 }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Cannot set unsupported config value y.")
|
109
|
-
end
|
110
|
-
|
111
|
-
it "raises an error when you set an arbitrary config option with .y 10" do
|
112
|
-
expect(lambda { StrictClass.y 10 }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Cannot set unsupported config value y.")
|
113
|
-
end
|
114
|
-
|
115
|
-
it "raises an error when you set an arbitrary config option with [:y] = 10" do
|
116
|
-
expect(lambda { StrictClass[:y] = 10 }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Cannot set unsupported config value y.")
|
117
|
-
end
|
118
|
-
|
119
|
-
it "does not break config_context_list" do
|
120
|
-
expect(lambda do
|
121
|
-
StrictClass.class_eval do
|
122
|
-
config_context_list(:lists, :list) do
|
123
|
-
default :y, 20
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end).not_to raise_error
|
127
|
-
end
|
128
|
-
|
129
|
-
it "does not break config_context_hash" do
|
130
|
-
expect(lambda do
|
131
|
-
StrictClass.class_eval do
|
132
|
-
config_context_hash(:hashes, :hash) do
|
133
|
-
default :z, 20
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end).not_to raise_error
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe "when a block has been used to set config values" do
|
141
|
-
before do
|
142
|
-
ConfigIt.configure { |c| c[:cookbook_path] = "monkey_rabbit"; c[:otherthing] = "boo" }
|
143
|
-
end
|
144
|
-
|
145
|
-
{ cookbook_path: "monkey_rabbit", otherthing: "boo" }.each do |k, v|
|
146
|
-
it "allows you to retrieve the config value for #{k} via []" do
|
147
|
-
expect(ConfigIt[k]).to eql(v)
|
148
|
-
end
|
149
|
-
it "allows you to retrieve the config value for #{k} via method_missing" do
|
150
|
-
expect(ConfigIt.send(k)).to eql(v)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
it "doesn't raise an ArgumentError if you access a config option that does not exist" do
|
156
|
-
expect(lambda { ConfigIt[:snob_hobbery] }).to_not raise_error
|
157
|
-
end
|
158
|
-
|
159
|
-
it "returns true or false with has_key?" do
|
160
|
-
expect(ConfigIt.has_key?(:monkey)).to be false
|
161
|
-
ConfigIt[:monkey] = "gotcha"
|
162
|
-
expect(ConfigIt.has_key?(:monkey)).to be true
|
163
|
-
end
|
164
|
-
|
165
|
-
it "returns true or false with key?" do
|
166
|
-
expect(ConfigIt.key?(:monkey2)).to be false
|
167
|
-
ConfigIt[:monkey2] = "gotcha"
|
168
|
-
expect(ConfigIt.key?(:monkey2)).to be true
|
169
|
-
end
|
170
|
-
|
171
|
-
describe "when a class method override writer exists" do
|
172
|
-
before do
|
173
|
-
@klass = Class.new
|
174
|
-
@klass.extend(::Mixlib::Config)
|
175
|
-
@klass.class_eval do
|
176
|
-
config_attr_writer :test_method do |blah|
|
177
|
-
blah.is_a?(Integer) ? blah * 1000 : blah
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
it "multiplies an integer by 1000" do
|
183
|
-
@klass[:test_method] = 53
|
184
|
-
expect(@klass[:test_method]).to eql(53000)
|
185
|
-
end
|
186
|
-
|
187
|
-
it "multiplies an integer by 1000 with the method_missing form" do
|
188
|
-
@klass.test_method = 63
|
189
|
-
expect(@klass.test_method).to eql(63000)
|
190
|
-
end
|
191
|
-
|
192
|
-
it "multiplies an integer by 1000 with the instance_eval DSL form" do
|
193
|
-
@klass.instance_eval("test_method 73")
|
194
|
-
expect(@klass.test_method).to eql(73000)
|
195
|
-
end
|
196
|
-
|
197
|
-
it "multiplies an integer by 1000 via from-file, too" do
|
198
|
-
allow(IO).to receive(:read).with("config.rb").and_return("test_method 99")
|
199
|
-
@klass.from_file("config.rb")
|
200
|
-
expect(@klass.test_method).to eql(99000)
|
201
|
-
end
|
202
|
-
|
203
|
-
it "receives internal_set with the method name and config value" do
|
204
|
-
expect(@klass).to receive(:internal_set).with(:test_method, 53).and_return(true)
|
205
|
-
@klass[:test_method] = 53
|
206
|
-
end
|
207
|
-
|
208
|
-
end
|
209
|
-
|
210
|
-
describe "When a configurable exists" do
|
211
|
-
before :each do
|
212
|
-
@klass = Class.new
|
213
|
-
@klass.extend(::Mixlib::Config)
|
214
|
-
@klass.class_eval do
|
215
|
-
configurable :daemonizeme
|
216
|
-
default :a, 1
|
217
|
-
config_attr_writer(:b) { |v| v }
|
218
|
-
config_context(:c)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
it "Getter methods are created for the configurable" do
|
223
|
-
expect(@klass.respond_to?(:daemonizeme)).to be true
|
224
|
-
expect(@klass.respond_to?(:a)).to be true
|
225
|
-
expect(@klass.respond_to?(:b)).to be true
|
226
|
-
expect(@klass.respond_to?(:c)).to be true
|
227
|
-
expect(@klass.respond_to?(:z)).to be false
|
228
|
-
end
|
229
|
-
|
230
|
-
it "Setter methods are created for the configurable" do
|
231
|
-
expect(@klass.respond_to?("daemonizeme=".to_sym)).to be true
|
232
|
-
expect(@klass.respond_to?("a=".to_sym)).to be true
|
233
|
-
expect(@klass.respond_to?("b=".to_sym)).to be true
|
234
|
-
expect(@klass.respond_to?("c=".to_sym)).to be true
|
235
|
-
expect(@klass.respond_to?("z=".to_sym)).to be false
|
236
|
-
end
|
237
|
-
|
238
|
-
describe "and extra methods have been dumped into Object" do
|
239
|
-
class NopeError < StandardError
|
240
|
-
end
|
241
|
-
before :each do
|
242
|
-
Object.send :define_method, :daemonizeme do
|
243
|
-
raise NopeError, "NOPE"
|
244
|
-
end
|
245
|
-
Object.send :define_method, "daemonizeme=".to_sym do
|
246
|
-
raise NopeError, "NOPE"
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
after do
|
251
|
-
Object.send :remove_method, :daemonizeme
|
252
|
-
Object.send :remove_method, :'daemonizeme='
|
253
|
-
end
|
254
|
-
|
255
|
-
it "Normal classes call the extra method" do
|
256
|
-
normal_class = Class.new
|
257
|
-
normal_class.extend(::Mixlib::Config)
|
258
|
-
expect(lambda { normal_class.daemonizeme }).to raise_error(NopeError)
|
259
|
-
end
|
260
|
-
|
261
|
-
it "Configurables with the same name as the extra method can be set" do
|
262
|
-
@klass.daemonizeme = 10
|
263
|
-
expect(@klass[:daemonizeme]).to eql(10)
|
264
|
-
end
|
265
|
-
|
266
|
-
it "Configurables with the same name as the extra method can be retrieved" do
|
267
|
-
@klass[:daemonizeme] = 10
|
268
|
-
expect(@klass.daemonizeme).to eql(10)
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
describe "When config has a default value" do
|
274
|
-
before :each do
|
275
|
-
@klass = Class.new
|
276
|
-
@klass.extend(::Mixlib::Config)
|
277
|
-
@klass.class_eval { default :attr, 4 }
|
278
|
-
end
|
279
|
-
|
280
|
-
it "defaults to that value" do
|
281
|
-
expect(@klass.attr).to eql(4)
|
282
|
-
end
|
283
|
-
|
284
|
-
it "defaults to that value when retrieved as a hash" do
|
285
|
-
expect(@klass[:attr]).to eql(4)
|
286
|
-
end
|
287
|
-
|
288
|
-
it "is settable to another value" do
|
289
|
-
@klass.attr 5
|
290
|
-
expect(@klass.attr).to eql(5)
|
291
|
-
end
|
292
|
-
|
293
|
-
it "still defaults to that value after delete" do
|
294
|
-
@klass.attr 5
|
295
|
-
@klass.delete(:attr)
|
296
|
-
expect(@klass.attr).to eql(4)
|
297
|
-
end
|
298
|
-
|
299
|
-
it "still defaults to that value after reset" do
|
300
|
-
@klass.attr 5
|
301
|
-
@klass.reset
|
302
|
-
expect(@klass.attr).to eql(4)
|
303
|
-
end
|
304
|
-
|
305
|
-
it "save should not save anything for it" do
|
306
|
-
expect(@klass.save).to eql({})
|
307
|
-
end
|
308
|
-
|
309
|
-
it "save with include_defaults should save all defaults" do
|
310
|
-
expect(@klass.save(true)).to eql({ attr: 4 })
|
311
|
-
end
|
312
|
-
|
313
|
-
it "saves the new value if it gets set" do
|
314
|
-
@klass.attr 5
|
315
|
-
expect((saved = @klass.save)).to eql({ attr: 5 })
|
316
|
-
@klass.reset
|
317
|
-
expect(@klass.attr).to eql(4)
|
318
|
-
@klass.restore(saved)
|
319
|
-
expect(@klass.attr).to eql(5)
|
320
|
-
end
|
321
|
-
|
322
|
-
it "saves the new value even if it is set to its default value" do
|
323
|
-
@klass.attr 4
|
324
|
-
expect((saved = @klass.save)).to eql({ attr: 4 })
|
325
|
-
@klass.reset
|
326
|
-
expect(@klass.save).to eql({})
|
327
|
-
@klass.restore(saved)
|
328
|
-
expect(@klass.save).to eql({ attr: 4 })
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
describe "When config has a default value block" do
|
333
|
-
before :each do
|
334
|
-
@klass = Class.new
|
335
|
-
@klass.extend(::Mixlib::Config)
|
336
|
-
@klass.class_eval do
|
337
|
-
default :x, 4
|
338
|
-
default(:attr) { x * 2 }
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
it "defaults to that value" do
|
343
|
-
expect(@klass.attr).to eql(8)
|
344
|
-
end
|
345
|
-
|
346
|
-
it "is recalculated each time it is retrieved" do
|
347
|
-
expect(@klass.attr).to eql(8)
|
348
|
-
@klass.x = 2
|
349
|
-
expect(@klass.attr).to eql(4)
|
350
|
-
end
|
351
|
-
|
352
|
-
it "defaults to that value when retrieved as a hash" do
|
353
|
-
expect(@klass[:attr]).to eql(8)
|
354
|
-
end
|
355
|
-
|
356
|
-
it "is settable to another value" do
|
357
|
-
@klass.attr 5
|
358
|
-
expect(@klass.attr).to eql(5)
|
359
|
-
end
|
360
|
-
|
361
|
-
it "still defaults to that value after delete" do
|
362
|
-
@klass.attr 5
|
363
|
-
@klass.delete(:attr)
|
364
|
-
expect(@klass.attr).to eql(8)
|
365
|
-
end
|
366
|
-
|
367
|
-
it "still defaults to that value after reset" do
|
368
|
-
@klass.attr 5
|
369
|
-
@klass.reset
|
370
|
-
expect(@klass.attr).to eql(8)
|
371
|
-
end
|
372
|
-
|
373
|
-
it "save should not save anything for it" do
|
374
|
-
expect(@klass.save).to eql({})
|
375
|
-
end
|
376
|
-
|
377
|
-
it "save with include_defaults should save all defaults" do
|
378
|
-
expect(@klass.save(true)).to eql({ attr: 8, x: 4 })
|
379
|
-
end
|
380
|
-
|
381
|
-
it "saves the new value if it gets set" do
|
382
|
-
@klass.attr 5
|
383
|
-
expect((saved = @klass.save)).to eql({ attr: 5 })
|
384
|
-
@klass.reset
|
385
|
-
expect(@klass.attr).to eql(8)
|
386
|
-
@klass.restore(saved)
|
387
|
-
expect(@klass.attr).to eql(5)
|
388
|
-
end
|
389
|
-
|
390
|
-
it "saves the new value even if it is set to its default value" do
|
391
|
-
@klass.attr 8
|
392
|
-
expect((saved = @klass.save)).to eql({ attr: 8 })
|
393
|
-
@klass.reset
|
394
|
-
expect(@klass.save).to eql({})
|
395
|
-
@klass.restore(saved)
|
396
|
-
expect(@klass.save).to eql({ attr: 8 })
|
397
|
-
end
|
398
|
-
end
|
399
|
-
|
400
|
-
describe "When config has an array default value" do
|
401
|
-
before :each do
|
402
|
-
@klass = Class.new
|
403
|
-
@klass.extend(::Mixlib::Config)
|
404
|
-
@klass.class_eval { default :attr, [] }
|
405
|
-
end
|
406
|
-
|
407
|
-
it "reset clears it to its default" do
|
408
|
-
@klass.attr << "x"
|
409
|
-
expect(@klass.attr).to eql([ "x" ])
|
410
|
-
@klass.reset
|
411
|
-
expect(@klass.attr).to eql([])
|
412
|
-
end
|
413
|
-
|
414
|
-
it "save should not save anything for it" do
|
415
|
-
expect(@klass.save).to eql({})
|
416
|
-
end
|
417
|
-
|
418
|
-
it "save with include_defaults should save all defaults" do
|
419
|
-
expect(@klass.save(true)).to eql({ attr: [] })
|
420
|
-
end
|
421
|
-
|
422
|
-
it "saves the new value if it gets set" do
|
423
|
-
@klass.attr << "x"
|
424
|
-
expect((saved = @klass.save)).to eql({ attr: [ "x" ] })
|
425
|
-
@klass.reset
|
426
|
-
expect(@klass.attr).to eql([])
|
427
|
-
@klass.restore(saved)
|
428
|
-
expect(@klass.attr).to eql([ "x" ])
|
429
|
-
end
|
430
|
-
|
431
|
-
it "saves the new value even if it is set to its default value" do
|
432
|
-
@klass.attr = []
|
433
|
-
expect((saved = @klass.save)).to eql({ attr: [] })
|
434
|
-
@klass.reset
|
435
|
-
expect(@klass.save).to eql({})
|
436
|
-
@klass.restore(saved)
|
437
|
-
expect(@klass.save).to eql({ attr: [] })
|
438
|
-
end
|
439
|
-
end
|
440
|
-
|
441
|
-
describe "When config has a hash default value" do
|
442
|
-
before :each do
|
443
|
-
@klass = Class.new
|
444
|
-
@klass.extend(::Mixlib::Config)
|
445
|
-
@klass.class_eval { default :attr, {} }
|
446
|
-
end
|
447
|
-
|
448
|
-
it "reset clears it to its default" do
|
449
|
-
@klass.attr[:x] = 10
|
450
|
-
expect(@klass.attr[:x]).to eql(10)
|
451
|
-
@klass.reset
|
452
|
-
expect(@klass.attr[:x]).to be_nil
|
453
|
-
end
|
454
|
-
|
455
|
-
it "save should not save anything for it" do
|
456
|
-
expect(@klass.save).to eql({})
|
457
|
-
end
|
458
|
-
|
459
|
-
it "save with include_defaults should save all defaults" do
|
460
|
-
expect(@klass.save(true)).to eql({ attr: {} })
|
461
|
-
end
|
462
|
-
|
463
|
-
it "saves the new value if it gets set" do
|
464
|
-
@klass.attr[:hi] = "lo"
|
465
|
-
expect((saved = @klass.save)).to eql({ attr: { hi: "lo" } })
|
466
|
-
@klass.reset
|
467
|
-
expect(@klass.attr).to eql({})
|
468
|
-
@klass.restore(saved)
|
469
|
-
expect(@klass.save).to eql({ attr: { hi: "lo" } })
|
470
|
-
end
|
471
|
-
|
472
|
-
it "saves the new value even if it is set to its default value" do
|
473
|
-
@klass.attr = {}
|
474
|
-
expect((saved = @klass.save)).to eql({ attr: {} })
|
475
|
-
@klass.reset
|
476
|
-
expect(@klass.save).to eql({})
|
477
|
-
@klass.restore(saved)
|
478
|
-
expect(@klass.save).to eql({ attr: {} })
|
479
|
-
end
|
480
|
-
end
|
481
|
-
|
482
|
-
describe "When config has a string default value" do
|
483
|
-
before :each do
|
484
|
-
@klass = Class.new
|
485
|
-
@klass.extend(::Mixlib::Config)
|
486
|
-
@klass.class_eval { default :attr, "hello" }
|
487
|
-
end
|
488
|
-
|
489
|
-
it "reset clears it to its default" do
|
490
|
-
@klass.attr << " world"
|
491
|
-
expect(@klass.attr).to eql("hello world")
|
492
|
-
@klass.reset
|
493
|
-
expect(@klass.attr).to eql("hello")
|
494
|
-
end
|
495
|
-
|
496
|
-
it "save should not save anything for it" do
|
497
|
-
expect(@klass.save).to eql({})
|
498
|
-
end
|
499
|
-
|
500
|
-
it "save with include_defaults should save all defaults" do
|
501
|
-
expect(@klass.save(true)).to eql({ attr: "hello" })
|
502
|
-
end
|
503
|
-
|
504
|
-
it "saves the new value if it gets set" do
|
505
|
-
@klass.attr << " world"
|
506
|
-
expect((saved = @klass.save)).to eql({ attr: "hello world" })
|
507
|
-
@klass.reset
|
508
|
-
expect(@klass.attr).to eql("hello")
|
509
|
-
@klass.restore(saved)
|
510
|
-
expect(@klass.attr).to eql("hello world")
|
511
|
-
end
|
512
|
-
|
513
|
-
it "saves the new value even if it is set to its default value" do
|
514
|
-
@klass.attr "hello world"
|
515
|
-
expect((saved = @klass.save)).to eql({ attr: "hello world" })
|
516
|
-
@klass.reset
|
517
|
-
expect(@klass.save).to eql({})
|
518
|
-
@klass.restore(saved)
|
519
|
-
expect(@klass.save).to eql({ attr: "hello world" })
|
520
|
-
end
|
521
|
-
end
|
522
|
-
|
523
|
-
describe "When config has a a default value block" do
|
524
|
-
before :each do
|
525
|
-
@klass = Class.new
|
526
|
-
@klass.extend(::Mixlib::Config)
|
527
|
-
@klass.class_eval do
|
528
|
-
default(:attr) { 4 }
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
it "defaults to that value" do
|
533
|
-
expect(@klass.attr).to eql(4)
|
534
|
-
end
|
535
|
-
|
536
|
-
it "defaults to that value when retrieved as a hash" do
|
537
|
-
expect(@klass[:attr]).to eql(4)
|
538
|
-
end
|
539
|
-
|
540
|
-
it "is settable to another value" do
|
541
|
-
@klass.attr 5
|
542
|
-
expect(@klass.attr).to eql(5)
|
543
|
-
expect(@klass[:attr]).to eql(5)
|
544
|
-
end
|
545
|
-
|
546
|
-
it "still defaults to that value after delete" do
|
547
|
-
@klass.attr 5
|
548
|
-
@klass.delete(:attr)
|
549
|
-
expect(@klass.attr).to eql(4)
|
550
|
-
end
|
551
|
-
|
552
|
-
it "still defaults to that value after reset" do
|
553
|
-
@klass.attr 5
|
554
|
-
@klass.reset
|
555
|
-
expect(@klass.attr).to eql(4)
|
556
|
-
end
|
557
|
-
|
558
|
-
it "save should not save anything for it" do
|
559
|
-
expect(@klass.save).to eql({})
|
560
|
-
end
|
561
|
-
|
562
|
-
it "save with include_defaults should save all defaults" do
|
563
|
-
expect(@klass.save(true)).to eql({ attr: 4 })
|
564
|
-
end
|
565
|
-
|
566
|
-
it "saves the new value if it gets set" do
|
567
|
-
@klass.attr 5
|
568
|
-
expect((saved = @klass.save)).to eql({ attr: 5 })
|
569
|
-
@klass.reset
|
570
|
-
expect(@klass.attr).to eql(4)
|
571
|
-
@klass.restore(saved)
|
572
|
-
expect(@klass.attr).to eql(5)
|
573
|
-
end
|
574
|
-
|
575
|
-
it "saves the new value even if it is set to its default value" do
|
576
|
-
@klass.attr 4
|
577
|
-
expect((saved = @klass.save)).to eql({ attr: 4 })
|
578
|
-
@klass.reset
|
579
|
-
expect(@klass.save).to eql({})
|
580
|
-
@klass.restore(saved)
|
581
|
-
expect(@klass.save).to eql({ attr: 4 })
|
582
|
-
end
|
583
|
-
end
|
584
|
-
|
585
|
-
describe "When a configurable exists with writer and default value" do
|
586
|
-
before :each do
|
587
|
-
@klass = Class.new
|
588
|
-
@klass.extend(::Mixlib::Config)
|
589
|
-
@klass.class_eval do
|
590
|
-
configurable(:attr) do |c|
|
591
|
-
c.defaults_to(4)
|
592
|
-
c.writes_value { |value| value * 2 }
|
593
|
-
end
|
594
|
-
end
|
595
|
-
end
|
596
|
-
|
597
|
-
it "defaults to that value" do
|
598
|
-
expect(@klass.attr).to eql(4)
|
599
|
-
end
|
600
|
-
|
601
|
-
it "defaults to that value when retrieved as a hash" do
|
602
|
-
expect(@klass[:attr]).to eql(4)
|
603
|
-
end
|
604
|
-
|
605
|
-
it "is settable to another value" do
|
606
|
-
@klass.attr 5
|
607
|
-
expect(@klass.attr).to eql(10)
|
608
|
-
expect(@klass[:attr]).to eql(10)
|
609
|
-
end
|
610
|
-
|
611
|
-
it "is settable to another value with attr=" do
|
612
|
-
@klass.attr = 5
|
613
|
-
expect(@klass.attr).to eql(10)
|
614
|
-
expect(@klass[:attr]).to eql(10)
|
615
|
-
end
|
616
|
-
|
617
|
-
it "is settable to another value with [:attr]=" do
|
618
|
-
@klass[:attr] = 5
|
619
|
-
expect(@klass.attr).to eql(10)
|
620
|
-
expect(@klass[:attr]).to eql(10)
|
621
|
-
end
|
622
|
-
|
623
|
-
it "still defaults to that value after delete" do
|
624
|
-
@klass.attr 5
|
625
|
-
@klass.delete(:attr)
|
626
|
-
expect(@klass.attr).to eql(4)
|
627
|
-
end
|
628
|
-
|
629
|
-
it "still defaults to that value after reset" do
|
630
|
-
@klass.attr 5
|
631
|
-
@klass.reset
|
632
|
-
expect(@klass.attr).to eql(4)
|
633
|
-
end
|
634
|
-
|
635
|
-
it "save should not save anything for it" do
|
636
|
-
expect(@klass.save).to eql({})
|
637
|
-
end
|
638
|
-
|
639
|
-
it "save with include_defaults should save all defaults" do
|
640
|
-
expect(@klass.save(true)).to eql({ attr: 4 })
|
641
|
-
end
|
642
|
-
|
643
|
-
it "saves the new value if it gets set" do
|
644
|
-
@klass.attr 5
|
645
|
-
expect((saved = @klass.save)).to eql({ attr: 10 })
|
646
|
-
@klass.reset
|
647
|
-
expect(@klass.attr).to eql(4)
|
648
|
-
@klass.restore(saved)
|
649
|
-
expect(@klass.attr).to eql(10)
|
650
|
-
end
|
651
|
-
|
652
|
-
it "saves the new value even if it is set to its default value" do
|
653
|
-
@klass.attr 4
|
654
|
-
expect((saved = @klass.save)).to eql({ attr: 8 })
|
655
|
-
@klass.reset
|
656
|
-
expect(@klass.save).to eql({})
|
657
|
-
@klass.restore(saved)
|
658
|
-
expect(@klass.save).to eql({ attr: 8 })
|
659
|
-
end
|
660
|
-
end
|
661
|
-
|
662
|
-
describe "When a configurable exists with writer and default value set in chained form" do
|
663
|
-
before :each do
|
664
|
-
@klass = Class.new
|
665
|
-
@klass.extend(::Mixlib::Config)
|
666
|
-
@klass.class_eval do
|
667
|
-
configurable(:attr).defaults_to(4).writes_value { |value| value * 2 }
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
|
-
it "defaults to that value" do
|
672
|
-
expect(@klass.attr).to eql(4)
|
673
|
-
end
|
674
|
-
|
675
|
-
it "defaults to that value when retrieved as a hash" do
|
676
|
-
expect(@klass[:attr]).to eql(4)
|
677
|
-
end
|
678
|
-
|
679
|
-
it "is settable to another value" do
|
680
|
-
@klass.attr 5
|
681
|
-
expect(@klass.attr).to eql(10)
|
682
|
-
expect(@klass[:attr]).to eql(10)
|
683
|
-
end
|
684
|
-
|
685
|
-
it "is settable to another value with attr=" do
|
686
|
-
@klass.attr = 5
|
687
|
-
expect(@klass.attr).to eql(10)
|
688
|
-
expect(@klass[:attr]).to eql(10)
|
689
|
-
end
|
690
|
-
|
691
|
-
it "is settable to another value with [:attr]=" do
|
692
|
-
@klass[:attr] = 5
|
693
|
-
expect(@klass.attr).to eql(10)
|
694
|
-
expect(@klass[:attr]).to eql(10)
|
695
|
-
end
|
696
|
-
|
697
|
-
it "still defaults to that value after delete" do
|
698
|
-
@klass.attr 5
|
699
|
-
@klass.delete(:attr)
|
700
|
-
expect(@klass.attr).to eql(4)
|
701
|
-
end
|
702
|
-
|
703
|
-
it "still defaults to that value after reset" do
|
704
|
-
@klass.attr 5
|
705
|
-
@klass.reset
|
706
|
-
expect(@klass.attr).to eql(4)
|
707
|
-
end
|
708
|
-
|
709
|
-
it "save should not save anything for it" do
|
710
|
-
expect(@klass.save).to eql({})
|
711
|
-
end
|
712
|
-
|
713
|
-
it "save with include_defaults should save all defaults" do
|
714
|
-
expect(@klass.save(true)).to eql({ attr: 4 })
|
715
|
-
end
|
716
|
-
|
717
|
-
it "saves the new value if it gets set" do
|
718
|
-
@klass.attr 5
|
719
|
-
expect((saved = @klass.save)).to eql({ attr: 10 })
|
720
|
-
@klass.reset
|
721
|
-
expect(@klass.attr).to eql(4)
|
722
|
-
@klass.restore(saved)
|
723
|
-
expect(@klass.attr).to eql(10)
|
724
|
-
end
|
725
|
-
|
726
|
-
it "saves the new value even if it is set to its default value" do
|
727
|
-
@klass.attr 2
|
728
|
-
expect((saved = @klass.save)).to eql({ attr: 4 })
|
729
|
-
@klass.reset
|
730
|
-
expect(@klass.save).to eql({})
|
731
|
-
@klass.restore(saved)
|
732
|
-
expect(@klass.save).to eql({ attr: 4 })
|
733
|
-
end
|
734
|
-
end
|
735
|
-
|
736
|
-
describe "When a configurable exists with a context" do
|
737
|
-
before :each do
|
738
|
-
@klass = Class.new
|
739
|
-
@klass.extend(::Mixlib::Config)
|
740
|
-
@klass.class_eval do
|
741
|
-
configurable :x
|
742
|
-
config_context(:blah) do
|
743
|
-
default :x, 5
|
744
|
-
end
|
745
|
-
end
|
746
|
-
end
|
747
|
-
|
748
|
-
it "configurable defaults in that context work" do
|
749
|
-
expect(@klass.blah.x).to eql(5)
|
750
|
-
end
|
751
|
-
|
752
|
-
it "after setting values in the context, the values remain set" do
|
753
|
-
@klass.blah.x = 10
|
754
|
-
expect(@klass.blah.x).to eql(10)
|
755
|
-
end
|
756
|
-
|
757
|
-
it "setting values with the same name in the parent context do not affect the child context" do
|
758
|
-
@klass.x = 10
|
759
|
-
expect(@klass.x).to eql(10)
|
760
|
-
expect(@klass.blah.x).to eql(5)
|
761
|
-
end
|
762
|
-
|
763
|
-
it "setting the entire context to a hash with default value overridden sets the value" do
|
764
|
-
@klass.blah = { x: 10 }
|
765
|
-
expect(@klass.blah.x).to eql(10)
|
766
|
-
end
|
767
|
-
|
768
|
-
it "setting the entire context to a hash sets non-default values" do
|
769
|
-
@klass.blah = { y: 10 }
|
770
|
-
expect(@klass.blah.x).to eql(5)
|
771
|
-
expect(@klass.blah.y).to eql(10)
|
772
|
-
end
|
773
|
-
|
774
|
-
it "setting the entire context to a hash deletes any non-default values and resets default values" do
|
775
|
-
@klass.blah.x = 10
|
776
|
-
@klass.blah.y = 10
|
777
|
-
@klass.blah = { z: 10 }
|
778
|
-
expect(@klass.blah.x).to eql(5)
|
779
|
-
expect(@klass.blah.y).to be_nil
|
780
|
-
expect(@klass.blah.z).to eql(10)
|
781
|
-
end
|
782
|
-
|
783
|
-
it "setting the context values in a block overrides the default values" do
|
784
|
-
@klass.blah do
|
785
|
-
x 10
|
786
|
-
y 20
|
787
|
-
end
|
788
|
-
expect(@klass.blah.x).to eq 10
|
789
|
-
expect(@klass.blah.y).to eq 20
|
790
|
-
end
|
791
|
-
|
792
|
-
it "setting the context values in a yielded block overrides the default values" do
|
793
|
-
@klass.blah do |b|
|
794
|
-
b.x = 10
|
795
|
-
b.y = 20
|
796
|
-
end
|
797
|
-
expect(@klass.blah.x).to eq 10
|
798
|
-
expect(@klass.blah.y).to eq 20
|
799
|
-
end
|
800
|
-
|
801
|
-
it "after reset of the parent class, children are reset" do
|
802
|
-
@klass.blah.x = 10
|
803
|
-
expect(@klass.blah.x).to eql(10)
|
804
|
-
@klass.reset
|
805
|
-
expect(@klass.blah.x).to eql(5)
|
806
|
-
end
|
807
|
-
|
808
|
-
it "save should not save anything for it by default" do
|
809
|
-
expect(@klass.save).to eql({})
|
810
|
-
end
|
811
|
-
|
812
|
-
it "save with include_defaults should save all defaults" do
|
813
|
-
expect(@klass.save(true)).to eql({ blah: { x: 5 } })
|
814
|
-
end
|
815
|
-
|
816
|
-
it "saves any new values that are set in the context" do
|
817
|
-
@klass.blah.x = 10
|
818
|
-
expect((saved = @klass.save)).to eql({ blah: { x: 10 } })
|
819
|
-
@klass.reset
|
820
|
-
expect(@klass.blah.x).to eql(5)
|
821
|
-
@klass.restore(saved)
|
822
|
-
expect(@klass.blah.x).to eql(10)
|
823
|
-
expect(@klass.save).to eql({ blah: { x: 10 } })
|
824
|
-
end
|
825
|
-
|
826
|
-
# this tests existing (somewhat bizzare) behavior of mixlib-config where testing to
|
827
|
-
# see if a key exists is equivalent to testing if the key has been set -- we can still
|
828
|
-
# retrieve the default value if it was set. the code in chef/chef which merges
|
829
|
-
# knife config values into cli values will be sensitive to this behavior.
|
830
|
-
it "defaults values do not show up when querying with #has_key?" do
|
831
|
-
expect(@klass.blah.has_key?(:x)).to be false
|
832
|
-
expect(@klass.blah.x).to be 5
|
833
|
-
end
|
834
|
-
|
835
|
-
it "if we assign the values, they show up when querying with #has_key?" do
|
836
|
-
@klass.blah.x = 5
|
837
|
-
expect(@klass.blah.has_key?(:x)).to be true
|
838
|
-
end
|
839
|
-
end
|
840
|
-
|
841
|
-
describe "When a configurable exists with a nested context" do
|
842
|
-
before :each do
|
843
|
-
@klass = Class.new
|
844
|
-
@klass.extend(::Mixlib::Config)
|
845
|
-
@klass.class_eval do
|
846
|
-
config_context(:blah) do
|
847
|
-
config_context(:yarr) do
|
848
|
-
default :x, 5
|
849
|
-
default :y, 6
|
850
|
-
end
|
851
|
-
end
|
852
|
-
configurable :x
|
853
|
-
end
|
854
|
-
end
|
855
|
-
|
856
|
-
it "configurable defaults in that context work" do
|
857
|
-
expect(@klass.blah.yarr.x).to eql(5)
|
858
|
-
expect(@klass.blah.yarr.y).to eql(6)
|
859
|
-
end
|
860
|
-
|
861
|
-
it "after setting values in the context, the values remain set" do
|
862
|
-
@klass.blah.yarr.x = 10
|
863
|
-
@klass.blah.yarr.y = 11
|
864
|
-
expect(@klass.blah.yarr.x).to eql(10)
|
865
|
-
expect(@klass.blah.yarr.y).to eql(11)
|
866
|
-
end
|
867
|
-
|
868
|
-
it "setting values with the same name in the parent context do not affect the child context" do
|
869
|
-
@klass.x = 10
|
870
|
-
expect(@klass.x).to eql(10)
|
871
|
-
expect(@klass.blah.yarr.x).to eql(5)
|
872
|
-
end
|
873
|
-
|
874
|
-
it "after reset of the parent class, children are reset" do
|
875
|
-
@klass.blah.yarr.x = 10
|
876
|
-
@klass.blah.yarr.y = 11
|
877
|
-
expect(@klass.blah.yarr.x).to eql(10)
|
878
|
-
expect(@klass.blah.yarr.y).to eql(11)
|
879
|
-
@klass.reset
|
880
|
-
expect(@klass.blah.yarr.x).to eql(5)
|
881
|
-
expect(@klass.blah.yarr.y).to eql(6)
|
882
|
-
end
|
883
|
-
|
884
|
-
it "save should not save anything for it by default" do
|
885
|
-
expect(@klass.save).to eql({})
|
886
|
-
end
|
887
|
-
|
888
|
-
it "save with include_defaults should save all defaults" do
|
889
|
-
expect(@klass.save(true)).to eql({ blah: { yarr: { x: 5, y: 6 } } })
|
890
|
-
end
|
891
|
-
|
892
|
-
it "saves any new values that are set in the context" do
|
893
|
-
@klass.blah.yarr.x = 10
|
894
|
-
@klass.blah.yarr.y = 11
|
895
|
-
expect((saved = @klass.save)).to eql({ blah: { yarr: { x: 10, y: 11 } } })
|
896
|
-
@klass.reset
|
897
|
-
expect(@klass.blah.yarr.x).to eql(5)
|
898
|
-
expect(@klass.blah.yarr.y).to eql(6)
|
899
|
-
@klass.restore(saved)
|
900
|
-
expect(@klass.blah.yarr.x).to eql(10)
|
901
|
-
expect(@klass.blah.yarr.y).to eql(11)
|
902
|
-
expect(@klass.save).to eql({ blah: { yarr: { x: 10, y: 11 } } })
|
903
|
-
end
|
904
|
-
|
905
|
-
it "restores defaults not included in saved data" do
|
906
|
-
@klass.restore( blah: { yarr: { x: 10 } } )
|
907
|
-
expect(@klass.blah.yarr.x).to eql(10)
|
908
|
-
expect(@klass.blah.yarr.y).to eql(6)
|
909
|
-
end
|
910
|
-
|
911
|
-
it "removes added properties not included in saved state" do
|
912
|
-
@klass.blah.yarr.z = 12
|
913
|
-
@klass.restore( blah: { yarr: { x: 10 } } )
|
914
|
-
expect(@klass.blah.yarr.x).to eql(10)
|
915
|
-
expect(@klass.blah.yarr.z).to eql(nil)
|
916
|
-
end
|
917
|
-
|
918
|
-
it "can set a config context from another context" do
|
919
|
-
@klass.blah.blyme = { x: 7 }
|
920
|
-
blyme = @klass.blah.blyme
|
921
|
-
@klass.blah.yarr.x = 12
|
922
|
-
@klass.blah.yarr = blyme
|
923
|
-
expect(@klass.blah.yarr.x).to eql(7)
|
924
|
-
end
|
925
|
-
end
|
926
|
-
|
927
|
-
describe "When a config_context with no defaulted values exists" do
|
928
|
-
before :each do
|
929
|
-
@klass = Class.new
|
930
|
-
@klass.extend(::Mixlib::Config)
|
931
|
-
@klass.class_eval do
|
932
|
-
config_context(:blah) do
|
933
|
-
configurable(:x)
|
934
|
-
end
|
935
|
-
end
|
936
|
-
end
|
937
|
-
|
938
|
-
it "has_key? finds the subcontext" do
|
939
|
-
expect(@klass.has_key?(:blah)).to be true
|
940
|
-
end
|
941
|
-
|
942
|
-
it "key? finds the subcontext" do
|
943
|
-
expect(@klass.key?(:blah)).to be true
|
944
|
-
end
|
945
|
-
|
946
|
-
it "save does not save the hash for the config_context" do
|
947
|
-
expect(@klass.save).to eql({})
|
948
|
-
end
|
949
|
-
|
950
|
-
it "save with defaults saves the hash for the config_context" do
|
951
|
-
expect(@klass.save(true)).to eql({ blah: {} })
|
952
|
-
end
|
953
|
-
end
|
954
|
-
|
955
|
-
describe "When a config_context with no configurables exists" do
|
956
|
-
before :each do
|
957
|
-
@klass = Class.new
|
958
|
-
@klass.extend(::Mixlib::Config)
|
959
|
-
@klass.class_eval do
|
960
|
-
config_context(:blah)
|
961
|
-
end
|
962
|
-
end
|
963
|
-
|
964
|
-
it "save does not save the hash for the config_context" do
|
965
|
-
expect(@klass.save).to eql({})
|
966
|
-
end
|
967
|
-
|
968
|
-
it "save with defaults saves the hash for the config_context" do
|
969
|
-
expect(@klass.save(true)).to eql({ blah: {} })
|
970
|
-
end
|
971
|
-
end
|
972
|
-
|
973
|
-
describe "When a nested context has strict mode on" do
|
974
|
-
class StrictClass2
|
975
|
-
extend ::Mixlib::Config
|
976
|
-
config_context :c do
|
977
|
-
config_strict_mode true
|
978
|
-
default :x, 1
|
979
|
-
end
|
980
|
-
end
|
981
|
-
|
982
|
-
it "The parent class allows you to set arbitrary config options" do
|
983
|
-
StrictClass2.y = 10
|
984
|
-
end
|
985
|
-
|
986
|
-
it "The nested class does not allow you to set arbitrary config options" do
|
987
|
-
expect(lambda { StrictClass2.c.y = 10 }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Cannot set unsupported config value y.")
|
988
|
-
end
|
989
|
-
end
|
990
|
-
|
991
|
-
describe "When strict mode is on but a nested context has strict mode unspecified" do
|
992
|
-
class StrictClass3
|
993
|
-
extend ::Mixlib::Config
|
994
|
-
config_strict_mode true
|
995
|
-
default :x, 1
|
996
|
-
config_context :c
|
997
|
-
end
|
998
|
-
|
999
|
-
it "The parent class does not allow you to set arbitrary config options" do
|
1000
|
-
expect(lambda { StrictClass3.y = 10 }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Cannot set unsupported config value y.")
|
1001
|
-
end
|
1002
|
-
|
1003
|
-
it "The nested class does not allow you to set arbitrary config options" do
|
1004
|
-
expect(lambda { StrictClass3.y = 10 }).to raise_error(Mixlib::Config::UnknownConfigOptionError, "Cannot set unsupported config value y.")
|
1005
|
-
end
|
1006
|
-
end
|
1007
|
-
|
1008
|
-
describe "When a config_context is opened twice" do
|
1009
|
-
before :each do
|
1010
|
-
@klass = Class.new
|
1011
|
-
@klass.extend(::Mixlib::Config)
|
1012
|
-
@klass.class_eval do
|
1013
|
-
config_context(:blah) do
|
1014
|
-
default :x, 10
|
1015
|
-
end
|
1016
|
-
config_context(:blah) do
|
1017
|
-
default :y, 20
|
1018
|
-
end
|
1019
|
-
end
|
1020
|
-
end
|
1021
|
-
|
1022
|
-
it "Both config_context blocks are honored" do
|
1023
|
-
@klass.blah.x == 10
|
1024
|
-
@klass.blah.y == 20
|
1025
|
-
end
|
1026
|
-
end
|
1027
|
-
|
1028
|
-
it "When a config_context is opened in place of a regular configurable, an error is raised" do
|
1029
|
-
klass = Class.new
|
1030
|
-
klass.extend(::Mixlib::Config)
|
1031
|
-
expect(lambda do
|
1032
|
-
klass.class_eval do
|
1033
|
-
default :blah, 10
|
1034
|
-
config_context(:blah) do
|
1035
|
-
default :y, 20
|
1036
|
-
end
|
1037
|
-
end
|
1038
|
-
end).to raise_error(Mixlib::Config::ReopenedConfigurableWithConfigContextError)
|
1039
|
-
end
|
1040
|
-
|
1041
|
-
it "When a config_context is opened in place of a regular configurable, an error is raised" do
|
1042
|
-
klass = Class.new
|
1043
|
-
klass.extend(::Mixlib::Config)
|
1044
|
-
expect(lambda do
|
1045
|
-
klass.class_eval do
|
1046
|
-
config_context(:blah) do
|
1047
|
-
default :y, 20
|
1048
|
-
end
|
1049
|
-
default :blah, 10
|
1050
|
-
end
|
1051
|
-
end).to raise_error(Mixlib::Config::ReopenedConfigContextWithConfigurableError)
|
1052
|
-
end
|
1053
|
-
|
1054
|
-
describe "config context lists" do
|
1055
|
-
let(:klass) do
|
1056
|
-
klass = Class.new
|
1057
|
-
klass.extend ::Mixlib::Config
|
1058
|
-
klass.instance_eval do
|
1059
|
-
config_context_list(:tests, :test) do
|
1060
|
-
default :y, 20
|
1061
|
-
end
|
1062
|
-
end
|
1063
|
-
klass
|
1064
|
-
end
|
1065
|
-
it "defines list methods when declaring a config_context_list" do
|
1066
|
-
expect(klass.methods).to include :test
|
1067
|
-
expect(klass.methods).to include :tests
|
1068
|
-
end
|
1069
|
-
|
1070
|
-
it "creates a new item each time the singular list is called" do
|
1071
|
-
klass.test do
|
1072
|
-
y 40
|
1073
|
-
end
|
1074
|
-
klass.test do
|
1075
|
-
y 50
|
1076
|
-
end
|
1077
|
-
expect(klass.tests.length).to be 2
|
1078
|
-
expect(klass.tests.first.y).to be 40
|
1079
|
-
expect(klass.tests.last.y).to be 50
|
1080
|
-
end
|
1081
|
-
|
1082
|
-
it "can save the config list" do
|
1083
|
-
klass.test do
|
1084
|
-
y 40
|
1085
|
-
end
|
1086
|
-
klass.test do
|
1087
|
-
y 50
|
1088
|
-
end
|
1089
|
-
expect(klass.save).to eq({
|
1090
|
-
tests: [
|
1091
|
-
{ y: 40 },
|
1092
|
-
{ y: 50 },
|
1093
|
-
],
|
1094
|
-
})
|
1095
|
-
end
|
1096
|
-
|
1097
|
-
it "can restore the config list from a hash" do
|
1098
|
-
hash = {
|
1099
|
-
tests: [
|
1100
|
-
{ y: 40 },
|
1101
|
-
{ y: 50 },
|
1102
|
-
],
|
1103
|
-
}
|
1104
|
-
klass.restore(hash)
|
1105
|
-
expect(klass.tests.length).to be 2
|
1106
|
-
expect(klass.tests.first.y).to be 40
|
1107
|
-
expect(klass.tests.last.y).to be 50
|
1108
|
-
end
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
describe "config context hashes" do
|
1112
|
-
let(:klass) do
|
1113
|
-
klass = Class.new
|
1114
|
-
klass.extend ::Mixlib::Config
|
1115
|
-
klass.instance_eval do
|
1116
|
-
config_context_hash(:tests, :test) do
|
1117
|
-
default :y, 20
|
1118
|
-
end
|
1119
|
-
end
|
1120
|
-
klass
|
1121
|
-
end
|
1122
|
-
|
1123
|
-
it "defines list methods when declaring a config_context_hash" do
|
1124
|
-
expect(klass.methods).to include :test
|
1125
|
-
expect(klass.methods).to include :tests
|
1126
|
-
end
|
1127
|
-
|
1128
|
-
context "when called with a new key each time" do
|
1129
|
-
it "creates a new item each time" do
|
1130
|
-
klass.test :one do
|
1131
|
-
y 40
|
1132
|
-
end
|
1133
|
-
klass.test :two do
|
1134
|
-
y 50
|
1135
|
-
end
|
1136
|
-
expect(klass.tests.length).to be 2
|
1137
|
-
expect(klass.tests[:one].y).to be 40
|
1138
|
-
expect(klass.tests[:two].y).to be 50
|
1139
|
-
end
|
1140
|
-
end
|
1141
|
-
context "when called with the same key" do
|
1142
|
-
it "modifies the existing value" do
|
1143
|
-
klass.test :only do
|
1144
|
-
y 40
|
1145
|
-
end
|
1146
|
-
klass.test :only do
|
1147
|
-
y 50
|
1148
|
-
end
|
1149
|
-
expect(klass.tests.length).to be 1
|
1150
|
-
expect(klass.tests[:only].y).to be 50
|
1151
|
-
end
|
1152
|
-
end
|
1153
|
-
|
1154
|
-
it "can save the config hash" do
|
1155
|
-
klass.test :one do
|
1156
|
-
y 40
|
1157
|
-
end
|
1158
|
-
klass.test :two do
|
1159
|
-
y 50
|
1160
|
-
end
|
1161
|
-
expect(klass.save).to eq({
|
1162
|
-
tests: {
|
1163
|
-
one: { y: 40 },
|
1164
|
-
two: { y: 50 },
|
1165
|
-
},
|
1166
|
-
})
|
1167
|
-
end
|
1168
|
-
|
1169
|
-
it "can restore the config hash from a hash" do
|
1170
|
-
hash = {
|
1171
|
-
tests: {
|
1172
|
-
one: { y: 40 },
|
1173
|
-
two: { y: 50 },
|
1174
|
-
},
|
1175
|
-
}
|
1176
|
-
klass.restore(hash)
|
1177
|
-
expect(klass.tests.length).to be 2
|
1178
|
-
expect(klass.tests[:one].y).to be 40
|
1179
|
-
expect(klass.tests[:two].y).to be 50
|
1180
|
-
end
|
1181
|
-
end
|
1182
|
-
|
1183
|
-
describe ".from_yaml" do
|
1184
|
-
let(:yaml) do
|
1185
|
-
<<-EOH
|
1186
|
-
---
|
1187
|
-
foo:
|
1188
|
-
- bar
|
1189
|
-
- baz
|
1190
|
-
- matazz
|
1191
|
-
alpha: beta
|
1192
|
-
EOH
|
1193
|
-
end
|
1194
|
-
|
1195
|
-
it "turns YAML into method-style setting" do
|
1196
|
-
allow(File).to receive(:exists?).and_return(true)
|
1197
|
-
allow(File).to receive(:readable?).and_return(true)
|
1198
|
-
allow(IO).to receive(:read).with("config.yml").and_return(yaml)
|
1199
|
-
|
1200
|
-
expect(lambda do
|
1201
|
-
ConfigIt.from_file("config.yml")
|
1202
|
-
end).to_not raise_error
|
1203
|
-
|
1204
|
-
expect(ConfigIt.foo).to eql(%w{ bar baz matazz })
|
1205
|
-
expect(ConfigIt.alpha).to eql("beta")
|
1206
|
-
end
|
1207
|
-
end
|
1208
|
-
|
1209
|
-
describe ".from_json" do
|
1210
|
-
let(:json) do
|
1211
|
-
<<-EOH
|
1212
|
-
{
|
1213
|
-
"foo": [
|
1214
|
-
"bar",
|
1215
|
-
"baz",
|
1216
|
-
"matazz"
|
1217
|
-
],
|
1218
|
-
"alpha": "beta"
|
1219
|
-
}
|
1220
|
-
EOH
|
1221
|
-
end
|
1222
|
-
|
1223
|
-
it "turns JSON into method-style setting" do
|
1224
|
-
allow(File).to receive(:exists?).and_return(true)
|
1225
|
-
allow(File).to receive(:readable?).and_return(true)
|
1226
|
-
allow(IO).to receive(:read).with("config.json").and_return(json)
|
1227
|
-
|
1228
|
-
expect(lambda do
|
1229
|
-
ConfigIt.from_file("config.json")
|
1230
|
-
end).to_not raise_error
|
1231
|
-
|
1232
|
-
expect(ConfigIt.foo).to eql(%w{ bar baz matazz })
|
1233
|
-
expect(ConfigIt.alpha).to eql("beta")
|
1234
|
-
end
|
1235
|
-
end
|
1236
|
-
|
1237
|
-
describe ".from_toml" do
|
1238
|
-
let(:toml) do
|
1239
|
-
<<-EOH
|
1240
|
-
foo = ["bar", "baz", "matazz"]
|
1241
|
-
alpha = "beta"
|
1242
|
-
EOH
|
1243
|
-
end
|
1244
|
-
|
1245
|
-
it "turns TOML into method-style setting" do
|
1246
|
-
allow(File).to receive(:exists?).and_return(true)
|
1247
|
-
allow(File).to receive(:readable?).and_return(true)
|
1248
|
-
allow(IO).to receive(:read).with("config.toml").and_return(toml)
|
1249
|
-
|
1250
|
-
expect(lambda do
|
1251
|
-
ConfigIt.from_file("config.toml")
|
1252
|
-
end).to_not raise_error
|
1253
|
-
|
1254
|
-
expect(ConfigIt.foo).to eql(%w{ bar baz matazz })
|
1255
|
-
expect(ConfigIt.alpha).to eql("beta")
|
1256
|
-
end
|
1257
|
-
end
|
1258
|
-
|
1259
|
-
describe ".from_hash" do
|
1260
|
-
let(:hash) do
|
1261
|
-
{
|
1262
|
-
"alpha" => "beta",
|
1263
|
-
"foo" => %w{ bar baz matazz},
|
1264
|
-
}
|
1265
|
-
end
|
1266
|
-
|
1267
|
-
it "translates the Hash into method-style" do
|
1268
|
-
ConfigIt.from_hash(hash)
|
1269
|
-
expect(ConfigIt.foo).to eql(%w{ bar baz matazz })
|
1270
|
-
expect(ConfigIt.alpha).to eql("beta")
|
1271
|
-
end
|
1272
|
-
end
|
1273
|
-
end
|