spec/mixlib/config_spec.rb in mixlib-config-2.2.4 vs spec/mixlib/config_spec.rb in mixlib-config-2.2.5

- old
+ new

@@ -28,32 +28,32 @@ it "loads a config file" do allow(File).to receive(:exists?).and_return(true) allow(File).to receive(:readable?).and_return(true) allow(IO).to receive(:read).with("config.rb").and_return("alpha = 'omega'\nfoo = 'bar'") - expect(lambda { + expect(lambda do ConfigIt.from_file("config.rb") - }).to_not raise_error + end).to_not raise_error end it "doesn't raise an ArgumentError with an explanation if you try and set a non-existent variable" do - expect(lambda { + expect(lambda do ConfigIt[:foobar] = "blah" - }).to_not raise_error + end).to_not raise_error end it "raises an Errno::ENOENT if it can't find the file" do - expect(lambda { + expect(lambda do ConfigIt.from_file("/tmp/timmytimmytimmy") - }).to raise_error(Errno::ENOENT) + end).to raise_error(Errno::ENOENT) end it "allows the error to bubble up when it's anything other than IOError" do allow(IO).to receive(:read).with("config.rb").and_return("@#asdf") - expect(lambda { + expect(lambda do ConfigIt.from_file("config.rb") - }).to raise_error(SyntaxError) + end).to raise_error(SyntaxError) end it "allows you to reference a value by index" do expect(ConfigIt[:alpha]).to eql("omega") end @@ -794,10 +794,24 @@ expect(@klass.blah.x).to eql(5) @klass.restore(saved) expect(@klass.blah.x).to eql(10) expect(@klass.save).to eql({ :blah => { :x => 10 } }) end + + # this tests existing (somewhat bizzare) behavior of mixlib-config where testing to + # see if a key exists is equivalent to testing if the key has been set -- we can still + # retrieve the default value if it was set. the code in chef/chef which merges + # knife config values into cli values will be sensitive to this behavior. + it "defaults values do not show up when querying with #has_key?" do + expect(@klass.blah.has_key?(:x)).to be false + expect(@klass.blah.x).to be 5 + end + + it "if we assign the values, they show up when querying with #has_key?" do + @klass.blah.x = 5 + expect(@klass.blah.has_key?(:x)).to be true + end end describe "When a configurable exists with a nested context" do before :each do @klass = Class.new @@ -1001,6 +1015,203 @@ default :blah, 10 end end).to raise_error(Mixlib::Config::ReopenedConfigContextWithConfigurableError) end + describe "config context lists" do + let(:klass) do + klass = Class.new + klass.extend ::Mixlib::Config + klass.instance_eval do + config_context_list(:tests, :test) do + default :y, 20 + end + end + klass + end + it "defines list methods when declaring a config_context_list" do + expect(klass.methods).to include :test + expect(klass.methods).to include :tests + end + + it "creates a new item each time the singular list is called" do + klass.test do + y 40 + end + klass.test do + y 50 + end + expect(klass.tests.length).to be 2 + expect(klass.tests.first.y).to be 40 + expect(klass.tests.last.y).to be 50 + end + + it "can save the config list" do + klass.test do + y 40 + end + klass.test do + y 50 + end + expect(klass.save).to eq({ + tests: [ + { y: 40 }, + { y: 50 }, + ], + }) + end + + it "can restore the config list from a hash" do + hash = { + tests: [ + { y: 40 }, + { y: 50 }, + ], + } + klass.restore(hash) + expect(klass.tests.length).to be 2 + expect(klass.tests.first.y).to be 40 + expect(klass.tests.last.y).to be 50 + end + end + + describe "config context hashes" do + let(:klass) do + klass = Class.new + klass.extend ::Mixlib::Config + klass.instance_eval do + config_context_hash(:tests, :test) do + default :y, 20 + end + end + klass + end + + it "defines list methods when declaring a config_context_hash" do + expect(klass.methods).to include :test + expect(klass.methods).to include :tests + end + + context "when called with a new key each time" do + it "creates a new item each time" do + klass.test :one do + y 40 + end + klass.test :two do + y 50 + end + expect(klass.tests.length).to be 2 + expect(klass.tests[:one].y).to be 40 + expect(klass.tests[:two].y).to be 50 + end + end + context "when called with the same key" do + it "modifies the existing value" do + klass.test :only do + y 40 + end + klass.test :only do + y 50 + end + expect(klass.tests.length).to be 1 + expect(klass.tests[:only].y).to be 50 + end + end + + it "can save the config hash" do + klass.test :one do + y 40 + end + klass.test :two do + y 50 + end + expect(klass.save).to eq({ + tests: { + one: { y: 40 }, + two: { y: 50 }, + }, + }) + end + + it "can restore the config hash from a hash" do + hash = { + tests: { + one: { y: 40 }, + two: { y: 50 }, + }, + } + klass.restore(hash) + expect(klass.tests.length).to be 2 + expect(klass.tests[:one].y).to be 40 + expect(klass.tests[:two].y).to be 50 + end + end + + describe ".from_yaml" do + let(:yaml) do + <<-EOH +--- +foo: + - bar + - baz + - matazz +alpha: beta + EOH + end + + it "turns YAML into method-style setting" do + allow(File).to receive(:exists?).and_return(true) + allow(File).to receive(:readable?).and_return(true) + allow(IO).to receive(:read).with("config.yml").and_return(yaml) + + expect(lambda do + ConfigIt.from_file("config.yml") + end).to_not raise_error + + expect(ConfigIt.foo).to eql(%w{ bar baz matazz }) + expect(ConfigIt.alpha).to eql("beta") + end + end + + describe ".from_json" do + let(:json) do + <<-EOH +{ + "foo": [ + "bar", + "baz", + "matazz" + ], + "alpha": "beta" +} + EOH + end + + it "turns YAML into method-style setting" do + allow(File).to receive(:exists?).and_return(true) + allow(File).to receive(:readable?).and_return(true) + allow(IO).to receive(:read).with("config.json").and_return(json) + + expect(lambda do + ConfigIt.from_file("config.json") + end).to_not raise_error + + expect(ConfigIt.foo).to eql(%w{ bar baz matazz }) + expect(ConfigIt.alpha).to eql("beta") + end + end + + describe ".from_hash" do + let(:hash) do + { + "alpha" => "beta", + "foo" => %w{ bar baz matazz}, + } + end + + it "translates the Hash into method-style" do + ConfigIt.from_hash(hash) + expect(ConfigIt.foo).to eql(%w{ bar baz matazz }) + expect(ConfigIt.alpha).to eql("beta") + end + end end