Skip to content

Commit

Permalink
Add R10K::CLI spec tests
Browse files Browse the repository at this point in the history
  • Loading branch information
nabertrand committed Jul 11, 2019
1 parent 8fbe0e7 commit 5515f6c
Show file tree
Hide file tree
Showing 4 changed files with 404 additions and 5 deletions.
27 changes: 27 additions & 0 deletions spec/shared-contexts/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
shared_context 'cli' do
def exit_with_code_and_message(r10k_args, code = 0, message = nil, out = 'stdout')
expect do
expect { r10k.run(r10k_args) }.to exit_with(code)
end.to output(message).send("to_#{out}".to_sym)
end

def filtered_extra_args
extra_args.reject { |arg| arg == '--' }
end

def string_to_module(str)
str.split('::').inject(Object) { |o, c| o.const_get c }
end

def setup_mock_run(command)
command.block = lambda do |opts, args, cmd|
[opts, args.to_a, cmd]
end
end

def setup_mock_runner(command, klass)
command.block = lambda do |opts, args, cmd|
klass.new(opts, args.to_a, cmd)
end
end
end
182 changes: 182 additions & 0 deletions spec/shared-examples/cli.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
shared_examples 'missing argument' do |option, optinfo|
it 'prints error and exits 1' do
["--#{option}", optinfo[:short]].compact.each do |opt|
exit_with_code_and_message(command_args + [opt] + extra_args, 1, %r{option requires an argument}, 'stderr')
end
end
end

shared_examples 'accepts option' do |option, optinfo, value|
it 'accepts the option' do
["--#{option}", optinfo[:short]].compact.each do |opt|
expect(r10k.run(command_args + [opt, value].compact + extra_args)).to eq([{ option.to_sym => value || true }, filtered_extra_args, command])
end
end
end

shared_examples 'help option' do |option, optinfo|
context "when #{option} specified" do
it 'prints command help and exits 0' do
["--#{option}", optinfo[:short]].compact.each do |help_arg|
expect(command).to receive(:help).and_call_original
exit_with_code_and_message(command_args + [help_arg] + extra_args, 0, %r{USAGE\s*r10k #{command_args.join(' ')}})
end
end
end
end

shared_examples 'Cri argument parsing' do |options, include_parent_examples|
context 'Cri argument parsing' do
let!(:prev_run) { command.block }

before(:each) do
setup_mock_run(command)
end

after(:each) do
command.block = prev_run
end

options.each do |option, optinfo|
if optinfo[:custom_cri_examples]
optinfo[:custom_cri_examples].each do |examples|
include_examples examples, option, optinfo
end
next
end

case optinfo[:type]
when :required
context "when #{option} specified without an argument" do
include_examples 'missing argument', option, optinfo
end

context "when #{option} specified with an argument" do
include_examples 'accepts option', option, optinfo, optinfo[:value]
end
when :optional
context "when #{option} specified without an argument" do
include_examples 'accepts option', option, optinfo, nil
end

context "when #{option} specified with an argument" do
include_examples 'accepts option', option, optinfo, optinfo[:value]
end
when :flag
context "when #{option} specified" do
include_examples 'accepts option', option, optinfo, nil
end
else
raise ArgumentError, "Unknown option type #{optinfo} for #{option}"
end
end

include_examples 'parent command examples' if include_parent_examples
end
end

shared_examples 'parent command examples' do
context 'with no arguments' do
it 'prints command help and exits 0' do
command.block = prev_run
expect(command).to receive(:help).and_call_original
exit_with_code_and_message(command_args, 0, %r{USAGE\s*r10k #{command_args.join(' ')}})
end
end

context 'with unknown argument' do
let(:command_args) { super() + ['invalid_arg'] }

it 'prints error to stderr and exits 1' do
exit_with_code_and_message(command_args, 1, %r{unknown command 'invalid_arg'}, 'stderr')
end
end
end

shared_examples 'Action argument parsing' do |options|
context 'Action argument parsing' do
def instance(opts = [])
r10k.run(command_args + opts.compact + extra_args).instance_variable_get(:@runner).instance
end

context 'CriRunner' do
it do
expect(r10k.run(command_args + extra_args)).to be_an_instance_of(R10K::Action::CriRunner)
end
end

context 'Runner' do
it do
expect(r10k.run(command_args + extra_args).instance_variable_get(:@runner)).to be_an_instance_of(R10K::Action::Runner)
end
end

context 'Action' do
it do
expect(instance).to be_an_instance_of(action_class)
end
end

options.each do |option, optinfo|
if optinfo[:custom_action_examples]
optinfo[:custom_action_examples].each do |examples|
include_examples examples, option, optinfo
end
next
end

context "when #{option} specified" do
let(:option_variable) do
"@#{option.to_s.sub(%r{^-*}, '')}".tr('-', '_').to_sym
end

if CRI_RUNNER_OPTIONS.include? option
it 'CriRunner processes the option' do
["--#{option}", optinfo[:short]].compact.each do |opt|
expect(instance([opt, optinfo[:value]]).instance_variable_defined?(option_variable)).to be false
end
end
else
it 'has the option set' do
["--#{option}", optinfo[:short]].compact.each do |opt|
expect(instance([opt, optinfo[:value]]).instance_variable_get(option_variable)).to eq(optinfo[:value] || true)
end
end
end
it 'processes extra args correctly' do
["--#{option}", optinfo[:short]].compact.each do |opt|
expect(instance([opt, optinfo[:value]]).instance_variable_get(:@argv)).to eq(filtered_extra_args)
end
end
end
end

context 'when no options specified' do
it 'processes extra args correctly' do
expect(instance.instance_variable_get(:@argv)).to eq(filtered_extra_args)
end
end
end
end

shared_examples 'deploy examples' do
before(:each) do
allow(File).to receive(:executable?).with('/path/to/puppet').and_return('true')
end
end

shared_examples 'version examples' do
context 'with no arguments' do
it 'prints r10k version' do
exit_with_code_and_message(command_args, 0, "r10k #{R10K::VERSION}\n")
end
end

context 'with -v or --verbose' do
it 'prints verbose version info' do
['-v', '--verbose'].each do |option|
exit_with_code_and_message(command_args + [option], 0, %r{r10k #{Regexp.quote(R10K::VERSION)}\n#{Regexp.quote(RUBY_DESCRIPTION)}})
end
end
end
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

Dir.glob(File.expand_path('spec/shared-examples/**/*.rb', PROJECT_ROOT)).each { |file| require file }

require 'shared-contexts/cli'
require 'shared-contexts/git-fixtures'
require 'matchers/exit_with'
require 'matchers/match_realpath'
Expand Down
Loading

0 comments on commit 5515f6c

Please sign in to comment.