diff options
author | Kyrylo Silin <silin@kyrylo.org> | 2019-04-04 02:46:45 +0300 |
---|---|---|
committer | Kyrylo Silin <silin@kyrylo.org> | 2019-04-04 02:46:45 +0300 |
commit | c0716319c2bc82c5393ef25aad4cdd9a9ca900da (patch) | |
tree | 9a372765425dc511e28ba49655e7906977cd4817 | |
parent | be0acf0a6744f9a9a79b0fce4875ee1d56743752 (diff) | |
download | pry-c0716319c2bc82c5393ef25aad4cdd9a9ca900da.tar.gz |
command_set: refactor specs
In this change we:
* Used modern RSpec API
* Deleted unused methods
-rw-r--r-- | lib/pry/command_set.rb | 45 | ||||
-rw-r--r-- | spec/command_set_spec.rb | 782 |
2 files changed, 288 insertions, 539 deletions
diff --git a/lib/pry/command_set.rb b/lib/pry/command_set.rb index 737a5cf7..57d7884e 100644 --- a/lib/pry/command_set.rb +++ b/lib/pry/command_set.rb @@ -171,7 +171,7 @@ class Pry def find_command_by_match_or_listing(match_or_listing) cmd = (@commands[match_or_listing] || Pry::Helpers::BaseHelpers.find_command(match_or_listing, @commands)) - cmd || raise(ArgumentError, "Cannot find a command: '#{match_or_listing}'!") + cmd || raise(ArgumentError, "cannot find a command: '#{match_or_listing}'") end # Aliases a command @@ -186,7 +186,7 @@ class Pry # @example Pass explicit description (overriding default). # Pry.config.commands.alias_command "lM", "ls -M", :desc => "cutiepie" def alias_command(match, action, options = {}) - (cmd = find_command(action)) || raise("Command: `#{action}` not found") + (cmd = find_command(action)) || raise("command: '#{action}' not found") original_options = cmd.options.dup options = original_options.merge!( @@ -201,6 +201,7 @@ class Pry run action, *args end + # TODO: untested. What's this about? c.class_eval do define_method(:complete) do |input| cmd.new(context).complete(input) @@ -254,22 +255,6 @@ class Pry cmd.description = description end - # Defines helpers methods for this command sets. - # Those helpers are only defined in this command set. - # - # @yield A block defining helper methods - # @example - # helpers do - # def hello - # puts "Hello!" - # end - # - # include OtherModule - # end - def helpers(&block) - helper_module.class_eval(&block) - end - # @return [Array] # The list of commands provided by the command set. def list_commands @@ -371,12 +356,6 @@ class Pry end end - # @private (used for testing) - def run_command(context, match, *args) - (command = @commands[match]) || raise(NoCommandError.new(match, self)) - command.new(context).call_safely(*args) - end - # Generate completions for the user's search. # @param [String] search The line to search for # @param [Hash] context The context to create the command with @@ -391,6 +370,24 @@ class Pry keys.map { |key| key + " " } end end + + private + + # Defines helpers methods for this command sets. + # Those helpers are only defined in this command set. + # + # @yield A block defining helper methods + # @example + # helpers do + # def hello + # puts "Hello!" + # end + # + # include OtherModule + # end + def helpers(&block) + helper_module.class_eval(&block) + end end # Wraps the return result of process_commands, indicates if the diff --git a/spec/command_set_spec.rb b/spec/command_set_spec.rb index 9899c060..de2b1307 100644 --- a/spec/command_set_spec.rb +++ b/spec/command_set_spec.rb @@ -1,669 +1,421 @@ -describe Pry::CommandSet do - before do - @set = Pry::CommandSet.new do - import Pry::Commands - end +RSpec.describe Pry::CommandSet do + let(:set) do + Pry::CommandSet.new { import(Pry::Commands) } + end - @ctx = { + let(:ctx) do + { target: binding, - command_set: @set, + command_set: set, pry_instance: Pry.new(output: StringIO.new) } end - describe "[]=" do - it "removes a command from the command set" do - expect(@set["help"]).not_to eq nil - @set["help"] = nil - expect(@set["help"]).to eq nil - expect { @set.run_command(TOPLEVEL_BINDING, "help") } - .to raise_error Pry::NoCommandError + describe "#new" do + it "merges other set with itself" do + other_set = described_class.new + other_set.command('test') {} + expect(described_class.new(other_set).count).to eq(1) end - it "replaces a command" do - old_help = @set["help"] - @set["help"] = @set["pry-version"] - expect(@set["help"]).not_to eq old_help + context "when block given" do + it "instance evals the block" do + other = described_class.new do + command('test') {} + end + expect(described_class.new(other).count).to eq(1) + end end + end - it "rebinds the command with key" do - @set["help-1"] = @set["help"] - expect(@set["help-1"].match).to eq "help-1" + describe "#block_command" do + it "defines a new command" do + subject.block_command('test') + expect(subject.count).to eq(1) end - it "raises a TypeError when command is not a subclass of Pry::Command" do - expect { @set["help"] = "hello" }.to raise_error TypeError + it "assings default description" do + command = subject.block_command('test') + expect(command.description).to eq('No description.') end - end - it 'should call the block used for the command when it is called' do - run = false - @set.command 'foo' do - run = true + it "can overwrite default description" do + command = subject.block_command('test', 'test description') + expect(command.description).to eq('test description') end - @set.run_command @ctx, 'foo' - expect(run).to eq true - end - - it 'should pass arguments of the command to the block' do - expect do |probe| - @set.command('foo', &probe) - @set.run_command(@ctx, 'foo', 1, 2, 3) - end.to yield_with_args(1, 2, 3) - end - - it 'should use the first argument as context' do - inside = inner_scope do |probe| - @set.command('foo', &probe) - - @set.run_command @ctx, 'foo' + it "configures command options" do + command = subject.block_command( + 'test', 'test description', some_option: 'some value' + ) + expect(command.options).to include(some_option: 'some value') end - expect(inside.context).to eq(@ctx) - end - - it 'should raise an error when calling an undefined command' do - @set.command('foo') {} - expect { @set.run_command @ctx, 'bar' }.to raise_error Pry::NoCommandError - end - - it 'should be able to remove its own commands' do - @set.command('foo') {} - @set.delete 'foo' - - expect { @set.run_command @ctx, 'foo' }.to raise_error Pry::NoCommandError - end - - it 'should be able to remove its own commands, by listing name' do - @set.command(/^foo1/, 'desc', listing: 'foo') {} - @set.delete 'foo' - - expect { @set.run_command @ctx, /^foo1/ }.to raise_error Pry::NoCommandError - end - - it 'should be able to import some commands from other sets' do - run = false - - other_set = Pry::CommandSet.new do - command('foo') { run = true } - command('bar') {} + context "when description is a hash" do + it "treats description as options" do + command = subject.block_command('test', some_option: 'some value') + expect(command.options).to include(some_option: 'some value') + end end - - @set.import_from(other_set, 'foo') - - @set.run_command @ctx, 'foo' - expect(run).to eq true - - expect { @set.run_command @ctx, 'bar' }.to raise_error Pry::NoCommandError end - it 'should return command set after import' do - run = false - - other_set = Pry::CommandSet.new do - command('foo') { run = true } - command('bar') {} + describe "#create_command" do + it "defines a new class command" do + subject.create_command('test') {} + expect(subject.count).to eq(1) end - expect(@set.import(other_set)).to eq @set - end - - it 'should return command set after import_from' do - run = false - - other_set = Pry::CommandSet.new do - command('foo') { run = true } - command('bar') {} + it "assings default description" do + command = subject.create_command('test') {} + expect(command.description).to eq('No description.') end - expect(@set.import_from(other_set, 'foo')).to eq @set - end - - it 'should be able to import some commands from other sets using listing name' do - run = false - - other_set = Pry::CommandSet.new do - command(/^foo1/, 'desc', listing: 'foo') { run = true } + it "can overwrite default description" do + command = subject.create_command('test', 'test description') {} + expect(command.description).to eq('test description') end - @set.import_from(other_set, 'foo') - - @set.run_command @ctx, /^foo1/ - expect(run).to eq true - end - - it 'should be able to import a whole set' do - run = [] - - other_set = Pry::CommandSet.new do - command('foo') { run << true } - command('bar') { run << true } + it "configures command options" do + command = subject.create_command( + 'test', 'test description', some_option: 'some value' + ) {} + expect(command.options).to include(some_option: 'some value') end - @set.import other_set - - @set.run_command @ctx, 'foo' - @set.run_command @ctx, 'bar' - expect(run).to eq [true, true] - end - - it 'should be able to import sets at creation' do - run = false - @set.command('foo') { run = true } - - Pry::CommandSet.new(@set).run_command @ctx, 'foo' - expect(run).to eq true - end - - it 'should set the descriptions of commands' do - @set.command('foo', 'some stuff') {} - expect(@set['foo'].description).to eq 'some stuff' - end - - describe "aliases" do - it 'should be able to alias command' do - run = false - @set.command('foo', 'stuff') { run = true } - - @set.alias_command 'bar', 'foo' - expect(@set['bar'].match).to eq 'bar' - expect(@set['bar'].description).to eq 'Alias for `foo`' - - @set.run_command @ctx, 'bar' - expect(run).to eq true + it "class_evals the given block in the command context" do + command = subject.create_command('test') do + description('class eval description') + end + expect(command.description).to eq('class eval description') end - it "should be able to alias command with command_prefix" do - run = false - - begin - @set.command('owl', 'stuff') { run = true } - @set.alias_command 'owlet', 'owl' - - Pry.config.command_prefix = '%' - expect(@set['%owlet'].match).to eq 'owlet' - expect(@set['%owlet'].description).to eq 'Alias for `owl`' - - @set.run_command @ctx, 'owlet' - expect(run).to eq true - ensure - Pry.config.command_prefix = '' + context "when description is a hash" do + it "treats description as options" do + command = subject.create_command('test', some_option: 'some value') {} + expect(command.options).to include(some_option: 'some value') end end + end - it 'should inherit options from original command' do - run = false - @set.command('foo', 'stuff', shellwords: true, interpolate: false) { run = true } - - @set.alias_command 'bar', 'foo' - expect(@set['bar'].options[:shellwords]).to eq @set['foo'].options[:shellwords] - expect(@set['bar'].options[:interpolate]).to eq @set['foo'].options[:interpolate] - - # however some options should not be inherited - expect(@set['bar'].options[:listing]).not_to eq @set['foo'].options[:listing] - expect(@set['bar'].options[:listing]).to eq "bar" + describe "#each" do + it "iterates over commands" do + subject.command('test') + expect(subject.each.first.first).to eq('test') end + end - it 'should be able to specify alias\'s description when aliasing' do - run = false - @set.command('foo', 'stuff') { run = true } + describe "#delete" do + it "deletes given commands" do + subject.command('peach') + subject.command('kiwi') + subject.command('apple') - @set.alias_command 'bar', 'foo', desc: "tobina" - expect(@set['bar'].match).to eq 'bar' - expect(@set['bar'].description).to eq "tobina" + subject.delete('kiwi', 'apple') - @set.run_command @ctx, 'bar' - expect(run).to eq true + expect(subject.count).to eq(1) end + end - it "should be able to alias a command by its invocation line" do - run = false - @set.command(/^foo1/, 'stuff', listing: 'foo') { run = true } - - @set.alias_command 'bar', 'foo1' - expect(@set['bar'].match).to eq 'bar' - expect(@set['bar'].description).to eq 'Alias for `foo1`' + describe "#import" do + let(:first_set) { described_class.new.tap { |set| set.command('first') } } + let(:second_set) { described_class.new.tap { |set| set.command('second') } } - @set.run_command @ctx, 'bar' - expect(run).to eq true + it "imports commands from given sets" do + subject.import(first_set, second_set) + expect(subject.count).to eq(2) end - it "should be able to specify options when creating alias" do - run = false - @set.command(/^foo1/, 'stuff', listing: 'foo') { run = true } - - @set.alias_command(/^b.r/, 'foo1', listing: "bar") - expect(@set.to_hash[/^b.r/].options[:listing]).to eq "bar" + it "returns self" do + expect(subject.import(first_set)).to eql(subject) end - it "should set description to default if description parameter is nil" do - run = false - @set.command(/^foo1/, 'stuff', listing: 'foo') { run = true } - - @set.alias_command "bar", 'foo1' - expect(@set["bar"].description).to eq "Alias for `foo1`" + it "includes given sets' helper modules" do + subject.import(first_set, second_set) + expect(subject.helper_module.ancestors.size).to eq(3) end end - it 'should be able to change the descriptions of commands' do - @set.command('foo', 'bar') {} - @set.desc 'foo', 'baz' - - expect(@set['foo'].description).to eq 'baz' - end - - it 'should get the descriptions of commands' do - @set.command('foo', 'bar') {} - expect(@set.desc('foo')).to eq 'bar' - end - - it 'should get the descriptions of commands, by listing' do - @set.command(/^foo1/, 'bar', listing: 'foo') {} - expect(@set.desc('foo')).to eq 'bar' - end - - it 'should return Pry::Command::VOID_VALUE for commands by default' do - @set.command('foo') { 3 } - expect(@set.run_command(@ctx, 'foo')).to eq Pry::Command::VOID_VALUE - end - - it 'should be able to keep return values' do - @set.command('foo', '', keep_retval: true) { 3 } - expect(@set.run_command(@ctx, 'foo')).to eq 3 - end - - it 'should be able to keep return values, even if return value is nil' do - @set.command('foo', '', keep_retval: true) { nil } - expect(@set.run_command(@ctx, 'foo')).to eq nil - end - - it 'should be able to have its own helpers' do - @set.command('foo') { my_helper } - @set.helpers { def my_helper; end } - - @set.run_command(@ctx, 'foo') - expect( - Pry::Command.subclass('foo', '', {}, Module.new).new(target: binding) - ).not_to(respond_to :my_helper) - end - - it 'should not recreate a new helper module when helpers is called' do - @set.command('foo') do - my_helper - my_other_helper + describe "#import_from" do + let(:other_set) do + set = described_class.new + set.command('kiwi') + set.command('peach') + set.command('plum') + set end - @set.helpers do - def my_helper; end + it "imports matching command from a set" do + subject.import_from(other_set, 'kiwi', 'peach') + expect(subject.count).to eq(2) end - @set.helpers do - def my_other_helper; end + it "returns self" do + expect(subject.import_from(other_set)).to eql(subject) end - @set.run_command(@ctx, 'foo') - end - - it 'should import helpers from imported sets' do - imported_set = Pry::CommandSet.new do - helpers do - def imported_helper_method; end - end + it "includes other set's helper module" do + subject.import_from(other_set) + expect(subject.helper_module.ancestors.size).to eq(2) end - - @set.import imported_set - @set.command('foo') { imported_helper_method } - @set.run_command(@ctx, 'foo') end - it 'should import helpers even if only some commands are imported' do - imported_set = Pry::CommandSet.new do - helpers do - def imported_helper_method; end - end - - command('bar') {} + describe "#find_command_by_match_or_listing" do + it "returns a matching by name command" do + subject.command('test') + command = subject.find_command_by_match_or_listing('test') + expect(command.command_name).to eq('test') end - @set.import_from imported_set, 'bar' - @set.command('foo') { imported_helper_method } - @set.run_command(@ctx, 'foo') - end - - it 'should provide a :listing for a command that defaults to its name' do - @set.command('foo', '') {} - expect(@set['foo'].options[:listing]).to eq 'foo' - end + it "returns a matching by listing command" do + subject.command('test', listing: 'wtf') + command = subject.find_command_by_match_or_listing('wtf') + expect(command.command_name).to eq('wtf') + end - it 'should provide a :listing for a command that differs from its name' do - @set.command('foo', '', listing: 'bar') {} - expect(@set['foo'].options[:listing]).to eq 'bar' + it "raises ArgumentError on non-matching command" do + expect { subject.find_command_by_match_or_listing('test') } + .to raise_error(ArgumentError, "cannot find a command: 'test'") + end end - it "should provide a 'help' command" do - @ctx[:command_set] = @set - @ctx[:output] = StringIO.new + describe "#alias_command" do + before { subject.command('test') } - expect { @set.run_command(@ctx, 'help') }.to_not raise_error - end - - describe "renaming a command" do - it 'should be able to rename and run a command' do - run = false - @set.command('foo') { run = true } - @set.rename_command('bar', 'foo') - @set.run_command(@ctx, 'bar') - expect(run).to eq true + it "returns the aliased command" do + new_command = subject.alias_command('new-test', 'test') + expect(new_command.command_name).to eq('new-test') end - it 'should accept listing name when renaming a command' do - run = false - @set.command('foo', "", listing: 'love') { run = true } - @set.rename_command('bar', 'love') - @set.run_command(@ctx, 'bar') - expect(run).to eq true + it "sets description for the aliased command automatically" do + new_command = subject.alias_command('new-test', 'test') + expect(new_command.description).to eq('Alias for `test`') end - it 'should raise exception trying to rename non-existent command' do - expect { @set.rename_command('bar', 'foo') }.to raise_error ArgumentError + it "sets aliased command's listing" do + new_command = subject.alias_command('new-test', 'test') + expect(new_command.options).to include(listing: 'new-test') end - it 'should make old command name inaccessible' do - @set.command('foo') {} - @set.rename_command('bar', 'foo') - expect { @set.run_command(@ctx, 'foo') }.to raise_error Pry::NoCommandError + it "sets group for the aliased command automatically" do + new_command = subject.alias_command('new-test', 'test') + expect(new_command.group).to eq('Aliases') end - it 'should be able to pass in options when renaming command' do - desc = "hello" - listing = "bing" - @set.command('foo') {} - @set.rename_command( - 'bar', 'foo', description: desc, listing: listing, keep_retval: true - ) - expect(@set['bar'].description).to eq desc - expect(@set['bar'].options[:listing]).to eq listing - expect(@set['bar'].options[:keep_retval]).to eq true + context "when string description is provided" do + it "uses the given description for the aliased command" do + new_command = subject.alias_command('new-test', 'test', desc: 'description') + expect(new_command.description).to eq('description') + end end - end - describe "before_* hook" do - it 'should be called before the original command' do - foo = [] - @set.command('foo') { foo << 1 } - @set['foo'].hooks.add_hook('before_foo', 'name') { foo << 2 } - @set.run_command(@ctx, 'foo') - - expect(foo).to eq [2, 1] + context "when non-string description is provided" do + it "uses the string representation of the given object" do + new_command = subject.alias_command('new-test', 'test', desc: Object.new) + expect(new_command.description).to match(/#<Object.+/) + end end - it 'should be called before the original command, using listing name' do - foo = [] - @set.command(/^foo1/, '', listing: 'foo') { foo << 1 } - cmd = @set.find_command_by_match_or_listing('foo') - cmd.hooks.add_hook('before_foo', 'name') { foo << 2 } - @set.run_command(@ctx, /^foo1/) - - expect(foo).to eq [2, 1] + context "when command doesn't match" do + it "raises RuntimeError" do + expect { subject.alias_command('nonexisting-command', 'action') } + .to raise_error(RuntimeError, "command: 'action' not found") + end end + end - it 'should share the context with the original command' do - @ctx[:target] = "test target string".__binding__ - before_val = nil - orig_val = nil - @set.command('foo') { orig_val = target } - @set['foo'].hooks.add_hook('before_foo', 'name') { before_val = target } - @set.run_command(@ctx, 'foo') + describe "#rename_command" do + before { subject.command('test') } - expect(before_val).to eq @ctx[:target] - expect(orig_val).to eq @ctx[:target] + it "renames a comamnd" do + subject.rename_command('new-name', 'test') + expect(subject['test']).to be_nil + expect(subject['new-name']).not_to be_nil end - it 'should work when applied multiple times' do - foo = [] - @set.command('foo') { foo << 1 } - @set['foo'].hooks.add_hook('before_foo', 'name1') { foo << 2 } - @set['foo'].hooks.add_hook('before_foo', 'name2') { foo << 3 } - @set['foo'].hooks.add_hook('before_foo', 'name3') { foo << 4 } - @set.run_command(@ctx, 'foo') - - expect(foo).to eq [2, 3, 4, 1] + it "can optionally set custom description" do + subject.rename_command('new-name', 'test', description: 'new description') + expect(subject['new-name'].description).to eq('new description') end - end - - describe "after_* hooks" do - it 'should be called after the original command' do - foo = [] - @set.command('foo') { foo << 1 } - @set['foo'].hooks.add_hook('after_foo', 'name') { foo << 2 } - @set.run_command(@ctx, 'foo') - expect(foo).to eq [1, 2] + context "when provided command is not registered" do + it "raises ArgumentError" do + expect { subject.rename_command('new-name', 'unknown') } + .to raise_error(ArgumentError) + end end + end - it 'should be called after the original command, using listing name' do - foo = [] - @set.command(/^foo1/, '', listing: 'foo') { foo << 1 } - cmd = @set.find_command_by_match_or_listing('foo') - cmd.hooks.add_hook('after_foo', 'name') { foo << 2 } - @set.run_command(@ctx, /^foo1/) + describe "#desc" do + before { subject.command('test') } - expect(foo).to eq [1, 2] + it "sets command description" do + subject.desc('test', 'test description') + expect(subject['test'].description).to eq('test description') end - it 'should share the context with the original command' do - @ctx[:target] = "test target string".__binding__ - after_val = nil - orig_val = nil - @set.command('foo') { orig_val = target } - @set['foo'].hooks.add_hook('after_foo', 'name') { after_val = target } - @set.run_command(@ctx, 'foo') - - expect(after_val).to eq @ctx[:target] - expect(orig_val).to eq @ctx[:target] + it "gets command description" do + expect(subject.desc('test')).to eq('No description.') end + end - it 'should determine the return value for the command' do - @set.command('foo', 'bar', keep_retval: true) { 1 } - @set['foo'].hooks.add_hook('after_foo', 'name') { 2 } - expect(@set.run_command(@ctx, 'foo')).to eq 2 + describe "#list_commands" do + before do + subject.command('test-one') + subject.command('test-two') end - it 'should work when applied multiple times' do - foo = [] - @set.command('foo') { foo << 1 } - @set['foo'].hooks.add_hook('after_foo', 'name1') { foo << 2 } - @set['foo'].hooks.add_hook('after_foo', 'name2') { foo << 3 } - @set['foo'].hooks.add_hook('after_foo', 'name3') { foo << 4 } - @set.run_command(@ctx, 'foo') - - expect(foo).to eq [1, 2, 3, 4] + it "returns the list of commands" do + expect(subject.list_commands).to eq(%w[test-one test-two]) end end - describe "before_command and after_command" do - it 'should work when combining both before_command and after_command' do - foo = [] - @set.command('foo') { foo << 1 } - @set['foo'].hooks.add_hook('after_foo', 'name') { foo << 2 } - @set['foo'].hooks.add_hook('before_foo', 'name') { foo << 3 } - @set.run_command(@ctx, 'foo') + describe "#to_hash" do + before { subject.command('test') } - expect(foo).to eq [3, 1, 2] + it "converts commands to hash" do + expect(subject.to_hash).to include('test' => respond_to(:command_name)) end - end - describe 'find_command' do - it 'should find commands with the right string' do - cmd = @set.command('rincewind') {} - expect(@set.find_command('rincewind')).to eq cmd + it "doesn't mutate original commands" do + hash = subject.to_hash + hash['foo'] = 'bar' + expect(subject.to_hash).not_to include('foo') end + end - it 'should not find commands with spaces before' do - @set.command('luggage') {} - expect(@set.find_command(' luggage')).to eq nil - end + describe "#[]" do + context "when there's an unambiguous command" do + before { subject.command('test') } - it 'should find commands with arguments after' do - cmd = @set.command('vetinari') {} - expect(@set.find_command('vetinari --knock 3')).to eq cmd + it "selects the command according to the given pattern" do + expect(subject['test']).to respond_to(:command_name) + end end - it 'should find commands with names containing spaces' do - cmd = @set.command('nobby nobbs') {} - expect(@set.find_command('nobby nobbs --steal petty-cash')).to eq cmd - end + context "when there's an ambiguous command" do + before do + subject.command(/\.(.*)/) + subject.command(/\.*(.*)/) + end - it 'should find command defined by regex' do - cmd = @set.command(/(capt|captain) vimes/i) {} - expect(@set.find_command('Capt Vimes')).to eq cmd + it "prefers a command with a higher score" do + expect(subject['.foo'].command_name).to eq("/\\.(.*)/") + expect(subject['..foo'].command_name).to eq("/\\.*(.*)/") + end end + end - it 'should find commands defined by regex with arguments' do - cmd = @set.command(/(cpl|corporal) Carrot/i) {} - expect(@set.find_command('cpl carrot --write-home')).to eq cmd - end + describe "#[]=" do + before { subject.command('test') } - it 'should not find commands by listing' do - @set.command(/werewol(f|ve)s?/, 'only once a month', listing: "angua") {} - expect(@set.find_command('angua')).to eq nil + it "rebinds the command with key" do + subject['test-1'] = subject['test'] + expect(subject['test-1'].match).to eq('test-1') end - it 'should not find commands without command_prefix' do - begin - Pry.config.command_prefix = '%' - @set.command('detritus') {} - expect(@set.find_command('detritus')).to eq nil - ensure - Pry.config.command_prefix = '' + context "when given command is nil" do + it "deletes the command matching the pattern" do + subject['test'] = nil + expect(subject.count).to be_zero end end - it "should find commands that don't use the prefix" do - begin - Pry.config.command_prefix = '%' - cmd = @set.command('colon', 'Sergeant Fred', use_prefix: false) {} - expect(@set.find_command('colon')).to eq cmd - ensure - Pry.config.command_prefix = '' + context "when given command is not a subclass of Pry::Command" do + it "raises TypeError" do + expect { subject['test'] = 1 } + .to raise_error(TypeError, 'command is not a subclass of Pry::Command') end end + end - it "should find the command that has the longest match" do - @set.command(/\.(.*)/) {} - cmd2 = @set.command(/\.\|\|(.*)/) {} - expect(@set.find_command('.||')).to eq cmd2 - end - - it "should find the command that has the longest name" do - @set.command(/\.(.*)/) {} - cmd2 = @set.command('.||') {} - expect(@set.find_command('.||')).to eq cmd2 + describe "#add_command" do + it "adds a command" do + subject.add_command(Class.new(Pry::Command)) + expect(subject.count).to eq(1) end end - describe '.valid_command?' do - it 'should be true for commands that can be found' do - @set.command('archchancellor') - expect(@set.valid_command?('archchancellor of_the?(:University)')).to eq true - end + describe "#find_command_for_help" do + before { subject.command('test') } - it 'should be false for commands that can\'' do - expect(@set.valid_command?('def monkey(ape)')).to eq false + context "when the command can be found" do + it "returns the command" do + expect(subject.find_command_for_help('test')).to respond_to(:command_name) + end end - it 'should not cause argument interpolation' do - @set.command('hello') - # rubocop:disable Lint/InterpolationCheck - expect { @set.valid_command?('hello #{raise "futz"}') }.to_not raise_error - # rubocop:enable Lint/InterpolationCheck + context "when the command cannot be found" do + it "returns nil" do + expect(subject.find_command_for_help('foo')).to be_nil + end end end - describe '.process_line' do - it 'should return Result.new(false) if there is no matching command' do - result = @set.process_line('1 + 42') - expect(result.command?).to eq false - expect(result.void_command?).to eq false - expect(result.retval).to eq nil - end + describe "#valid_command?" do + before { subject.command('test') } - it 'should return Result.new(true, VOID) if the command is not keep_retval' do - @set.create_command('mrs-cake') do - def process - 42 - end + context "when command can be found" do + it "returns true" do + expect(subject.valid_command?('test')).to be_truthy end - - result = @set.process_line('mrs-cake') - expect(result.command?).to eq true - expect(result.void_command?).to eq true - expect(result.retval).to eq Pry::Command::VOID_VALUE end - it 'should return Result.new(true, retval) if the command is keep_retval' do - @set.create_command('magrat', 'the maiden', keep_retval: true) do - def process - 42 - end + context "when command cannot be found" do + it "returns false" do + expect(subject.valid_command?('foo')).to be_falsey end - - result = @set.process_line('magrat') - expect(result.command?).to eq true - expect(result.void_command?).to eq false - expect(result.retval).to eq 42 end + end - it 'should pass through context' do - ctx = { - eval_string: "bloomers", - pry_instance: Object.new, - output: StringIO.new, - target: binding - } + describe "#process_line" do + before { subject.command('test') {} } - inside = inner_scope do |probe| - @set.create_command('agnes') do - define_method(:process, &probe) - end + context "when the given line is a command" do + it "returns a command" do + expect(subject.process_line('test')).to be_command + end - @set.process_line('agnes', ctx) + it "returns a non-void command" do + expect(subject.process_line('test')).to be_void_command end - expect(inside.eval_string).to eq(ctx[:eval_string]) - expect(inside.output).to eq(ctx[:output]) - expect(inside.target).to eq(ctx[:target]) - expect(inside.pry_instance).to eq(ctx[:pry_instance]) - end + context "and context is provided" do + before { subject.command('test') { output.puts('kiwi') } } - it 'should add command_set to context' do - inside = inner_scope do |probe| - @set.create_command(/nann+y ogg+/) do - define_method(:process, &probe) + it "passes the context to the command" do + output = StringIO.new + subject.process_line('test', output: output) + expect(output.string).to eq("kiwi\n") end + end + end - @set.process_line('nannnnnny oggggg') + context "when the given line is not a command" do + it "returns not a command" do + expect(subject.process_line('abcdefg')).not_to be_command end - expect(inside.command_set).to eq(@set) + it "returns a void result" do + expect(subject.process_line('test')).to be_void_command + end end end + # TODO: rewrite this block. if defined?(Bond) - describe '.complete' do + describe "#complete" do it "should list all command names" do - @set.create_command('susan') {} - expect(@set.complete('sus')).to.include 'susan ' + set.create_command('susan') {} + expect(set.complete('sus')).to.include 'susan ' end it "should delegate to commands" do - @set.create_command('susan') do + set.create_command('susan') do def complete(_search) ['--foo'] end end - expect(@set.complete('susan ')).to eq ['--foo'] + expect(set.complete('susan ')).to eq ['--foo'] end end end |