Add test coverage for dynamic action hook support

This commit is contained in:
Chris Roberts 2020-03-03 16:16:55 -08:00
parent 660166720b
commit 3686aed72d
3 changed files with 249 additions and 28 deletions

View File

@ -39,10 +39,6 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do
expect(communicator).to receive(:test).with(/synthetic\.conf/)
end
it "should register an action hook" do
expect(VagrantPlugins::GuestDarwin::Plugin).to receive(:action_hook).with(:apfs_firmlinks, :after_synced_folders)
end
context "with guest path within existing directory" do
let(:guestpath) { "/Users/vagrant/workspace" }
@ -77,10 +73,6 @@ describe "VagrantPlugins::GuestDarwin::Cap::MountVmwareSharedFolder" do
expect(communicator).to receive(:sudo).with(%r{ln -s .+/System/Volumes/Data.+})
end
it "should register an action hook" do
expect(VagrantPlugins::GuestDarwin::Plugin).to receive(:action_hook).with(:apfs_firmlinks, :after_synced_folders)
end
context "when firmlink is provided by the system" do
before { expect(described_class).to receive(:system_firmlink?).and_return(true) }

View File

@ -7,6 +7,7 @@ describe Vagrant::Action::Warden do
end
def call(env)
env[:data] << 1 if env[:data]
@app.call(env)
end
@ -21,6 +22,7 @@ describe Vagrant::Action::Warden do
end
def call(env)
env[:data] << 2 if env[:data]
@app.call(env)
end
@ -90,35 +92,146 @@ describe Vagrant::Action::Warden do
expect(data.key?(:recover)).not_to be
end
context "when hook is defined" do
let(:hook) { double("hook") }
it "does not do a recovery sequence if NoMemoryError is raised" do
error_proc = Proc.new { raise NoMemoryError }
before do
data[:hook] = hook
allow(hook).to receive(:call)
instance = described_class.new([ExitAction, error_proc], data)
# The SystemExit should come through
expect { instance.call(data) }.to raise_error(NoMemoryError)
# The recover should not have been called
expect(data.key?(:recover)).not_to be
end
describe "dynamic action hooks" do
let(:data) { {data: []} }
let(:hook_action_name) { :action_two }
let(:plugin) do
h_name = hook_action_name
@plugin ||= Class.new(Vagrant.plugin("2")) do
name "Test Plugin"
action_hook(:before_test, h_name) do |hook|
hook.prepend(proc{ |env| env[:data] << :first })
end
end
end
it "should receive a before hook call" do
expect(hook).to receive(:call).with(:before_action_one)
described_class.new([ActionOne], data).call(data)
before { plugin }
after do
Vagrant.plugin("2").manager.unregister(@plugin) if @plugin
@plugin = nil
end
it "should receive an after hook call" do
expect(hook).to receive(:call).with(:after_action_one)
described_class.new([ActionOne], data).call(data)
it "should call hook before running action" do
instance = described_class.new([ActionTwo], data)
instance.call(data)
expect(data[:data].first).to eq(:first)
expect(data[:data].last).to eq(2)
end
it "should not receive any hook calls for proc instances" do
expect(hook).not_to receive(:call)
described_class.new([proc{|*_| :testing }], data).call(data)
context "when hook is appending to action" do
let(:plugin) do
@plugin ||= Class.new(Vagrant.plugin("2")) do
name "Test Plugin"
action_hook(:before_test, :action_two) do |hook|
hook.append(proc{ |env| env[:data] << :first })
end
end
end
it "should call hook after action when action is nested" do
instance = described_class.new([described_class.new([ActionTwo], data), ActionOne], data)
instance.call(data)
expect(data[:data][0]).to eq(2)
expect(data[:data][1]).to eq(:first)
expect(data[:data][2]).to eq(1)
end
end
it "should receive before and after calls for each class" do
expect(hook).to receive(:call).with(:before_action_one)
expect(hook).to receive(:call).with(:after_action_one)
expect(hook).to receive(:call).with(:before_action_two)
expect(hook).to receive(:call).with(:after_action_two)
described_class.new([ActionOne, proc{|*_| :testing }, ActionTwo], data).call(data)
context "when hook uses class name" do
let(:hook_action_name) { "ActionTwo" }
it "should execute the hook" do
instance = described_class.new([ActionTwo], data)
instance.call(data)
expect(data[:data]).to include(:first)
end
end
context "when action includes a namespace" do
module Vagrant
module Test
class ActionTest
def initialize(app, env)
@app = app
end
def call(env)
env[:data] << :test if env[:data]
@app.call(env)
end
end
end
end
let(:instance) { described_class.new([Vagrant::Test::ActionTest], data) }
context "when hook uses short snake case name" do
let(:hook_action_name) { :action_test }
it "should execute the hook" do
instance.call(data)
expect(data[:data]).to include(:first)
end
end
context "when hook uses partial snake case name" do
let(:hook_action_name) { :test_action_test }
it "should execute the hook" do
instance.call(data)
expect(data[:data]).to include(:first)
end
end
context "when hook uses full snake case name" do
let(:hook_action_name) { :vagrant_test_action_test }
it "should execute the hook" do
instance.call(data)
expect(data[:data]).to include(:first)
end
end
context "when hook uses short class name" do
let(:hook_action_name) { "ActionTest" }
it "should execute the hook" do
instance.call(data)
expect(data[:data]).to include(:first)
end
end
context "when hook uses partial namespace class name" do
let(:hook_action_name) { "Test::ActionTest" }
it "should execute the hook" do
instance.call(data)
expect(data[:data]).to include(:first)
end
end
context "when hook uses full namespace class name" do
let(:hook_action_name) { "Vagrant::Test::ActionTest" }
it "should execute the hook" do
instance.call(data)
expect(data[:data]).to include(:first)
end
end
end
end
end

View File

@ -11,6 +11,122 @@ describe Vagrant::Plugin::V2::Manager do
p
end
describe "#generate_hook_keys" do
it "should return array with one value" do
expect(subject.generate_hook_keys(:test_value)).to eq(["test_value"])
end
it "should return array with two values when key is camel cased" do
result = subject.generate_hook_keys("TestValue")
expect(result.size).to eq(2)
expect(result).to include("TestValue")
expect(result).to include("test_value")
end
it "should handle class/module value" do
result = subject.generate_hook_keys(Vagrant)
expect(result.size).to eq(2)
expect(result).to include("Vagrant")
expect(result).to include("vagrant")
end
it "should handle namespaced value" do
result = subject.generate_hook_keys(Vagrant::Plugin)
expect(result.size).to eq(4)
expect(result).to include("Vagrant::Plugin")
expect(result).to include("Plugin")
expect(result).to include("vagrant_plugin")
expect(result).to include("plugin")
end
end
describe "#find_action_hooks" do
let(:hook_name) { "Vagrant::Plugin" }
before do
h_name = hook_name
pA = plugin do |p|
p.action_hook(:test, h_name) { "hook_called" }
end
subject.register(pA)
end
it "should find hook with full namespace" do
hooks = subject.find_action_hooks(Vagrant::Plugin)
expect(hooks).not_to be_empty
expect(hooks.first.call).to eq("hook_called")
end
it "should not find hook with short class name" do
hooks = subject.find_action_hooks("Plugin")
expect(hooks).to be_empty
end
it "should not find hook with full snake cased name" do
hooks = subject.find_action_hooks(:vagrant_plugin)
expect(hooks).to be_empty
end
it "should not find hook with short snake cased name" do
hooks = subject.find_action_hooks("plugin")
expect(hooks).to be_empty
end
context "when hook uses full snake cased name" do
let(:hook_name) { :vagrant_plugin }
it "should find hook with full namespace" do
hooks = subject.find_action_hooks(Vagrant::Plugin)
expect(hooks).not_to be_empty
expect(hooks.first.call).to eq("hook_called")
end
it "should find hook with full snake cased name" do
hooks = subject.find_action_hooks(:vagrant_plugin)
expect(hooks).not_to be_empty
expect(hooks.first.call).to eq("hook_called")
end
it "should not find hook with short class name" do
hooks = subject.find_action_hooks("Plugin")
expect(hooks).to be_empty
end
it "should not find hook with short snake cased name" do
hooks = subject.find_action_hooks("plugin")
expect(hooks).to be_empty
end
end
context "when hook uses short snake cased name" do
let(:hook_name) { :plugin }
it "should find hook with full namespace" do
hooks = subject.find_action_hooks(Vagrant::Plugin)
expect(hooks).not_to be_empty
expect(hooks.first.call).to eq("hook_called")
end
it "should find hook with short class name" do
hooks = subject.find_action_hooks("Plugin")
expect(hooks).not_to be_empty
expect(hooks.first.call).to eq("hook_called")
end
it "should find hook with short snake cased name" do
hooks = subject.find_action_hooks("plugin")
expect(hooks).not_to be_empty
expect(hooks.first.call).to eq("hook_called")
end
it "should not find hook with full snake cased name" do
hooks = subject.find_action_hooks(:vagrant_plugin)
expect(hooks).to be_empty
end
end
end
describe "#action_hooks" do
it "should contain globally registered hooks" do
pA = plugin do |p|