require File.expand_path("../../base", __FILE__) require "vagrant/capability_host" describe Vagrant::CapabilityHost do include_context "capability_helpers" subject do Class.new do extend Vagrant::CapabilityHost end end describe "#initialize_capabilities! and #capability_host_chain" do it "raises an error if an explicit host is not found" do expect { subject.initialize_capabilities!(:foo, {}, {}) }. to raise_error(Vagrant::Errors::CapabilityHostExplicitNotDetected) end it "raises an error if a host can't be detected" do hosts = { foo: [detect_class(false), nil], bar: [detect_class(false), :foo], } expect { subject.initialize_capabilities!(nil, hosts, {}) }. to raise_error(Vagrant::Errors::CapabilityHostNotDetected) end it "passes on extra args to the detect method" do klass = Class.new do def detect?(*args) raise "detect: #{args.inspect}" end end hosts = { foo: [klass, nil], } expect { subject.initialize_capabilities!(nil, hosts, {}, 1, 2) }. to raise_error(RuntimeError, "detect: [1, 2]") end it "detects a basic child" do hosts = { foo: [detect_class(false), nil], bar: [detect_class(true), nil], baz: [detect_class(false), nil], } subject.initialize_capabilities!(nil, hosts, {}) chain = subject.capability_host_chain expect(chain.length).to eql(1) expect(chain[0][0]).to eql(:bar) end it "detects the host with the most parents (deepest) first" do hosts = { foo: [detect_class(true), nil], bar: [detect_class(true), :foo], baz: [detect_class(true), :bar], foo2: [detect_class(true), nil], bar2: [detect_class(true), :foo2], } subject.initialize_capabilities!(nil, hosts, {}) chain = subject.capability_host_chain expect(chain.length).to eql(3) expect(chain.map(&:first)).to eql([:baz, :bar, :foo]) end it "detects a forced host" do hosts = { foo: [detect_class(false), nil], bar: [detect_class(false), nil], baz: [detect_class(false), nil], } subject.initialize_capabilities!(:bar, hosts, {}) chain = subject.capability_host_chain expect(chain.length).to eql(1) expect(chain[0][0]).to eql(:bar) end end describe "#capability?" do before do host = nil hosts = { foo: [detect_class(true), nil], bar: [detect_class(true), :foo], } caps = { foo: { parent: Class.new }, bar: { self: Class.new }, } subject.initialize_capabilities!(host, hosts, caps) end it "does not have a non-existent capability" do expect(subject.capability?(:foo)).to be_false end it "has capabilities of itself" do expect(subject.capability?(:self)).to be_true end it "has capabilities of parent" do expect(subject.capability?(:parent)).to be_true end end describe "capability" do let(:caps) { {} } def init host = nil hosts = { foo: [detect_class(true), nil], bar: [detect_class(true), :foo], } subject.initialize_capabilities!(host, hosts, caps) end it "executes the capability" do caps[:bar] = { test: cap_instance(:test) } init expect { subject.capability(:test) }. to raise_error(RuntimeError, "cap: test []") end it "executes the capability with arguments" do caps[:bar] = { test: cap_instance(:test) } init expect { subject.capability(:test, 1) }. to raise_error(RuntimeError, "cap: test [1]") end it "raises an exception if the capability doesn't exist" do init expect { subject.capability(:what_is_this_i_dont_even) }. to raise_error(Vagrant::Errors::CapabilityNotFound) end it "raises an exception if the method doesn't exist on the module" do caps[:bar] = { test_is_corrupt: cap_instance(:test_is_corrupt, corrupt: true) } init expect { subject.capability(:test_is_corrupt) }. to raise_error(Vagrant::Errors::CapabilityInvalid) end end end