spec/commnad_spec.rb in command_mapper-0.1.2 vs spec/commnad_spec.rb in command_mapper-0.2.0

- old
+ new

@@ -67,44 +67,42 @@ module TestCommand class EmptyCommand < CommandMapper::Command end end + module TestCommand + class BaseClassWithOptions < CommandMapper::Command + option "--foo" + option "--bar" + end + + class InheritedOptions < BaseClassWithOptions + end + + class InheritsAndDefinesOptions < BaseClassWithOptions + option "--baz" + end + end + describe ".options" do subject { command_class } context "when the command has no defined options" do let(:command_class) { TestCommand::EmptyCommand } it { expect(subject.options).to be_empty } end context "and when the command inherits from another command class" do - module TestCommand - class BaseClassWithOptions < CommandMapper::Command - option "--foo" - option "--bar" - end - - class InheritedOptions < BaseClassWithOptions - end - end - let(:command_class) { TestCommand::InheritedOptions } let(:command_superclass) { TestCommand::BaseClassWithOptions } it "must copy the options defined in the superclass" do expect(subject.options).to eq(command_superclass.options) end context "and when the class defines options of it's own" do - module TestCommand - class InheritsAndDefinesOptions < BaseClassWithOptions - option "--baz" - end - end - let(:command_class) { TestCommand::InheritsAndDefinesOptions } it "must copy the options defined in the superclass" do expect(subject.options).to include(command_superclass.options) end @@ -118,10 +116,42 @@ end end end end + describe ".has_option?" do + subject { command_class } + + let(:name) { :bar } + + context "when the command has no defined options" do + let(:command_class) { TestCommand::EmptyCommand } + + it "must return false" do + expect(subject.has_option?(name)).to be(false) + end + end + + context "when the command does have defined options" do + let(:command_class) { TestCommand::BaseClassWithOptions } + + context "and has the option with the given name" do + it "must return true" do + expect(subject.has_option?(name)).to be(true) + end + end + + context "but does not have the option with the given name" do + let(:name) { :xxx } + + it "must return false" do + expect(subject.has_option?(name)).to be(false) + end + end + end + end + describe ".option" do module TestCommand class DefinesItsOwnOptions < CommandMapper::Command command 'test' do option '--foo' @@ -240,48 +270,81 @@ expect { command_class.option(flag) }.to raise_error(ArgumentError,"option #{flag.inspect} maps to method name ##{name} and cannot override the internal method with same name: ##{name}") end end + + context "when the option name conflicts with another defined argument" do + let(:command_class) do + Class.new(described_class) do + argument :foo + end + end + + let(:flag) { "--foo" } + let(:name) { :foo } + + it do + expect { + subject.option(flag) + }.to raise_error(ArgumentError,"option #{flag.inspect} with name #{name.inspect} conflicts with another argument with the same name") + end + end + + context "when the option name conflicts with another defined subcommand" do + let(:command_class) do + Class.new(described_class) do + subcommand 'foo' do + end + end + end + + let(:flag) { "--foo" } + let(:name) { :foo } + + it do + expect { + subject.option(flag) + }.to raise_error(ArgumentError,"option #{flag.inspect} with name #{name.inspect} conflicts with another subcommand with the same name") + end + end end + module TestCommand + class BaseClassWithArguments < CommandMapper::Command + argument :foo + argument :bar + end + + class InheritedArguments < BaseClassWithArguments + end + + class InheritsAndDefinesArguments < BaseClassWithArguments + argument :baz + end + end + describe ".arguments" do subject { command_class } context "when the command has no defined arguments" do let(:command_class) { TestCommand::EmptyCommand } it { expect(subject.arguments).to be_empty } end context "when the comand does have defined arguments" do - module TestCommand - class BaseClassWithOptions < CommandMapper::Command - argument :foo - argument :bar - end + let(:command_class) { TestCommand::InheritedArguments } + let(:command_superclass) { TestCommand::BaseClassWithArguments } - class InheritedOptions < BaseClassWithOptions - end - end - - let(:command_class) { TestCommand::InheritedOptions } - let(:command_superclass) { TestCommand::BaseClassWithOptions } - it "must copy the arguments defined in the superclass" do expect(subject.arguments).to eq(command_superclass.arguments) end context "and when the class defines arguments of it's own" do - module TestCommand - class InheritsAndDefinesOptions < BaseClassWithOptions - argument :baz - end - end + let(:command_class) { TestCommand::InheritsAndDefinesArguments } - let(:command_class) { TestCommand::InheritsAndDefinesOptions } - it "must copy the arguments defined in the superclass" do expect(subject.arguments).to include(command_superclass.arguments) end it "must define it's own arguments" do @@ -293,10 +356,42 @@ end end end end + describe ".has_argument?" do + subject { command_class } + + let(:name) { :bar } + + context "when the command has no defined arguments" do + let(:command_class) { TestCommand::EmptyCommand } + + it "must return false" do + expect(subject.has_argument?(name)).to be(false) + end + end + + context "when the command does have defined arguments" do + let(:command_class) { TestCommand::BaseClassWithArguments } + + context "and has the argument with the given name" do + it "must return true" do + expect(subject.has_argument?(name)).to be(true) + end + end + + context "but does not have the argument with the given name" do + let(:name) { :xxx } + + it "must return false" do + expect(subject.has_argument?(name)).to be(false) + end + end + end + end + describe ".argument" do module TestCommand class DefinesArgument < CommandMapper::Command command 'test' do argument :foo @@ -355,54 +450,85 @@ expect { command_class.argument(name) }.to raise_error(ArgumentError,"argument #{name.inspect} cannot override internal method with same name: ##{name}") end end + + context "when the argument name conflicts with another defined option" do + let(:command_class) do + Class.new(described_class) do + option '--foo' + end + end + + let(:name) { :foo } + + it do + expect { + subject.argument(name) + }.to raise_error(ArgumentError,"argument #{name.inspect} conflicts with another option with the same name") + end + end + + context "when the argument name conflicts with another defined subcommand" do + let(:command_class) do + Class.new(described_class) do + subcommand 'foo' do + end + end + end + + let(:name) { :foo } + + it do + expect { + subject.argument(name) + }.to raise_error(ArgumentError,"argument #{name.inspect} conflicts with another subcommand with the same name") + end + end end + module TestCommand + class BaseClassWithSubcommands < CommandMapper::Command + subcommand :foo do + end + + subcommand :bar do + end + end + + class InheritedSubcommands < BaseClassWithSubcommands + end + + class InheritsAndDefinesSubcommands < BaseClassWithSubcommands + + subcommand :baz do + end + + end + end + describe ".subcommands" do subject { command_class } context "when the command has no defined subcommands" do let(:command_class) { TestCommand::EmptyCommand } it { expect(subject.subcommands).to be_empty } end context "when the comand does have defined subcommands" do - module TestCommand - class BaseClassWithOptions < CommandMapper::Command - subcommand :foo do - end + let(:command_class) { TestCommand::InheritedSubcommands } + let(:command_superclass) { TestCommand::BaseClassWithSubcommands } - subcommand :bar do - end - end - - class InheritedOptions < BaseClassWithOptions - end - end - - let(:command_class) { TestCommand::InheritedOptions } - let(:command_superclass) { TestCommand::BaseClassWithOptions } - it "must copy the subcommands defined in the superclass" do expect(subject.subcommands).to eq(command_superclass.subcommands) end context "and when the class defines subcommands of it's own" do - module TestCommand - class InheritsAndDefinesOptions < BaseClassWithOptions + let(:command_class) { TestCommand::InheritsAndDefinesSubcommands } - subcommand :baz do - end - - end - end - - let(:command_class) { TestCommand::InheritsAndDefinesOptions } - it "must copy the subcommands defined in the superclass" do expect(subject.subcommands).to include(command_superclass.subcommands) end it "must define it's own subcommands" do @@ -414,10 +540,42 @@ end end end end + describe ".has_subcommand?" do + subject { command_class } + + let(:name) { :bar } + + context "when the command has no defined subcommands" do + let(:command_class) { TestCommand::EmptyCommand } + + it "must return false" do + expect(subject.has_subcommand?(name)).to be(false) + end + end + + context "when the command does have defined subcommands" do + let(:command_class) { TestCommand::BaseClassWithSubcommands } + + context "and has the subcommand with the given name" do + it "must return true" do + expect(subject.has_subcommand?(name)).to be(true) + end + end + + context "but does not have the subcommand with the given name" do + let(:name) { :xxx } + + it "must return false" do + expect(subject.has_subcommand?(name)).to be(false) + end + end + end + end + describe ".subcommand" do module TestCommand class DefinesSubcommand < CommandMapper::Command command 'cmd' do subcommand "subcmd" do @@ -565,15 +723,49 @@ let(:name) { "command-argv" } let(:method_name) { 'command_argv' } it do expect { - command_class.subcommand(name) do + subject.subcommand(name) do end }.to raise_error(ArgumentError,"subcommand #{name.inspect} maps to method name ##{method_name} and cannot override the internal method with same name: ##{method_name}") end end + + context "when the subcommand name conflicts with another defined option" do + let(:command_class) do + Class.new(described_class) do + option '--foo' + end + end + + let(:name) { 'foo' } + + it do + expect { + subject.subcommand(name) do + end + }.to raise_error(ArgumentError,"subcommand #{name.inspect} conflicts with another option with the same name") + end + end + + context "when the subcommand name conflicts with another defined argument" do + let(:command_class) do + Class.new(described_class) do + argument :foo + end + end + + let(:name) { 'foo' } + + it do + expect { + subject.subcommand(name) do + end + }.to raise_error(ArgumentError,"subcommand #{name.inspect} conflicts with another argument with the same name") + end + end end module TestCommand class ExampleCommand < CommandMapper::Command command 'test' do @@ -613,12 +805,12 @@ context "when called with a Hash of params" do let(:params) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the Hash of params and call #run" do - if RUBY_VERSION < '3.' + it "must initialize a new command with the Hash of params and call #run_command" do + if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby' expect(subject).to receive(:new).with({},params).and_return(command_instance) else expect(subject).to receive(:new).with(params).and_return(command_instance) end @@ -631,19 +823,57 @@ context "when called with keyword aguments" do let(:kwargs) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the keyword arguments and call #run" do + it "must initialize a new command with the keyword arguments and call #run_command" do expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance) expect(command_instance).to receive(:run_command).and_return(return_value) expect(subject.run(**kwargs)).to be(return_value) end end end + describe ".spawn" do + let(:command_instance) { double(:command_instance) } + let(:return_value) { double(:boolean) } + + subject { command_class } + + context "when called with a Hash of params" do + let(:params) do + {opt1: opt1, arg1: arg1} + end + + it "must initialize a new command with the Hash of params and call #spawn_command" do + if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby' + expect(subject).to receive(:new).with({},params).and_return(command_instance) + else + expect(subject).to receive(:new).with(params).and_return(command_instance) + end + + expect(command_instance).to receive(:spawn_command).and_return(return_value) + + expect(subject.spawn(params)).to be(return_value) + end + end + + context "when called with keyword aguments" do + let(:kwargs) do + {opt1: opt1, arg1: arg1} + end + + it "must initialize a new command with the keyword arguments and call #spawn_command" do + expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance) + expect(command_instance).to receive(:spawn_command).and_return(return_value) + + expect(subject.spawn(**kwargs)).to be(return_value) + end + end + end + describe ".capture" do let(:command_instance) { double(:command_instance) } let(:return_value) { double(:string) } subject { command_class } @@ -651,12 +881,12 @@ context "when called with a Hash of params" do let(:params) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the Hash of params and call #capture" do - if RUBY_VERSION < '3.' + it "must initialize a new command with the Hash of params and call #capture_command" do + if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby' expect(subject).to receive(:new).with({},params).and_return(command_instance) else expect(subject).to receive(:new).with(params).and_return(command_instance) end @@ -669,11 +899,11 @@ context "when called with keyword aguments" do let(:kwargs) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the keyword arguments and call #capture" do + it "must initialize a new command with the keyword arguments and call #capture_command" do expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance) expect(command_instance).to receive(:capture_command).and_return(return_value) expect(subject.capture(**kwargs)).to be(return_value) end @@ -689,12 +919,12 @@ context "when called with a Hash of params" do let(:params) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the Hash of params and call #popen" do - if RUBY_VERSION < '3.' + it "must initialize a new command with the Hash of params and call #popen_command" do + if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby' expect(subject).to receive(:new).with({},params).and_return(command_instance) else expect(subject).to receive(:new).with(params).and_return(command_instance) end @@ -707,11 +937,11 @@ context "when called with keyword aguments" do let(:kwargs) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the keyword arguments and call #popen" do + it "must initialize a new command with the keyword arguments and call #popen_command" do expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance) expect(command_instance).to receive(:popen_command).and_return(return_value) expect(subject.popen(**kwargs)).to be(return_value) end @@ -727,12 +957,12 @@ context "when called with a Hash of params" do let(:params) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the Hash of params and call #sudo" do - if RUBY_VERSION < '3.' + it "must initialize a new command with the Hash of params and call #sudo_command" do + if RUBY_VERSION < '3.' || RUBY_ENGINE == 'truffleruby' expect(subject).to receive(:new).with({},params).and_return(command_instance) else expect(subject).to receive(:new).with(params).and_return(command_instance) end @@ -745,11 +975,11 @@ context "when called with keyword aguments" do let(:kwargs) do {opt1: opt1, arg1: arg1} end - it "must initialize a new command with the keyword arguments and call #sudo" do + it "must initialize a new command with the keyword arguments and call #sudo_command" do expect(subject).to receive(:new).with({},**kwargs).and_return(command_instance) expect(command_instance).to receive(:sudo_command).and_return(return_value) expect(subject.sudo(**kwargs)).to be(return_value) end @@ -1118,12 +1348,22 @@ describe "#run_command" do subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) } it "must pass the command's env and argv to Kenrel.system" do - expect(subject).to receive(:system).with(env,*subject.command_argv) + expect(Kernel).to receive(:system).with(env,*subject.command_argv) subject.run_command + end + end + + describe "#spawn_command" do + subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) } + + it "must pass the command's env and argv to Kenrel.system" do + expect(Process).to receive(:spawn).with(env,*subject.command_argv) + + subject.spawn_command end end describe "#capture_command" do subject { command_class.new({opt1: opt1, arg1: arg1}, command_env: env) }