require "ostruct" require File.expand_path("../../../../base", __FILE__) describe Vagrant::Config::V1::Loader do include_context "unit" before(:each) do # Force the V1 loader to believe that we are in V1 stub_const("Vagrant::Config::CURRENT_VERSION", "1") end describe "empty" do it "returns an empty configuration object" do result = described_class.init expect(result).to be_kind_of(Vagrant::Config::V1::Root) end it "returns an object with all configuration keys loaded if V1" do # Make sure we're version 1 stub_const("Vagrant::Config::CURRENT_VERSION", "1") # Register some config classes. register_plugin("1") do |p| p.config("foo") { OpenStruct } p.config("bar", true) { OpenStruct } end # Test that we have all keys result = described_class.init expect(result.foo).to be_kind_of(OpenStruct) expect(result.bar).to be_kind_of(OpenStruct) end it "returns only upgradable config objects if not V1" do # Make sure we're NOT version 1 stub_const("Vagrant::Config::CURRENT_VERSION", "2") # Register some config classes. register_plugin("1") do |p| p.config("foo") { OpenStruct } p.config("bar", true) { OpenStruct } end # Test that we have all keys result = described_class.init expect(result.bar).to be_kind_of(OpenStruct) end end describe "finalizing" do it "should call `#finalize` on the configuration object" do # Register a plugin for our test register_plugin("1") do |plugin| plugin.config "foo" do Class.new do attr_accessor :bar def finalize! @bar = "finalized" end end end end # Create the proc we're testing config_proc = Proc.new do |config| config.foo.bar = "value" end # Test that it works properly config = described_class.load(config_proc) expect(config.foo.bar).to eq("value") # Finalize it described_class.finalize(config) expect(config.foo.bar).to eq("finalized") end end describe "loading" do it "should configure with all plugin config keys loaded" do # Register a plugin for our test register_plugin("1") do |plugin| plugin.config("foo") { OpenStruct } end # Create the proc we're testing config_proc = Proc.new do |config| config.foo.bar = "value" end # Test that it works properly config = described_class.load(config_proc) expect(config.foo.bar).to eq("value") end end describe "merging" do it "should merge available configuration keys" do old = Vagrant::Config::V1::Root.new({ foo: Object }) new = Vagrant::Config::V1::Root.new({ bar: Object }) result = described_class.merge(old, new) expect(result.foo).to be_kind_of(Object) expect(result.bar).to be_kind_of(Object) end it "should merge instantiated objects" do config_class = Class.new do attr_accessor :value end old = Vagrant::Config::V1::Root.new({ foo: config_class }) old.foo.value = "old" new = Vagrant::Config::V1::Root.new({ bar: config_class }) new.bar.value = "new" result = described_class.merge(old, new) expect(result.foo.value).to eq("old") expect(result.bar.value).to eq("new") end it "should merge conflicting classes by calling `merge`" do config_class = Class.new do attr_accessor :value def merge(new) result = self.class.new result.value = @value + new.value result end end old = Vagrant::Config::V1::Root.new({ foo: config_class }) old.foo.value = 10 new = Vagrant::Config::V1::Root.new({ foo: config_class }) new.foo.value = 15 result = described_class.merge(old, new) expect(result.foo.value).to eq(25) end end end