1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00
pry--pry/spec/pry_spec.rb
Josh Cheek 144d32e1d6 Switch test suite to RSpec
Removes Bacon and Mocha

Reasoning explained in this comment: https://github.com/pry/pry/issues/277#issuecomment-51708712

Mostly this went smoothly. There were a few errors that I fixed along
the way, e.g. tests that were failing but for various reasons still
passed. Should have documented them, but didn't think about it until
very near the end. But generaly, I remember 2 reasons this would happen:
`lambda { raise "omg" }.should.raise(RuntimeError, /not-omg/)` will pass
because the second argument is ignored by Bacon. And `1.should == 2`
will return false instead of raising an error when it is not in an it
block (e.g. if stuck in a describe block, that would just return false)

The only one that I felt unsure about was spec/helpers/table_spec.rb
`Pry::Helpers.tablify_or_one_line('head', %w(ing)).should == 'head: ing'`
This is wrong, but was not failing because it was in a describe block
instead of an it block.  In reality, it returns `"head: ing\n"`,
I updated the test to reflect this, though I don't know for sure
this is the right thing to do

This will fail on master until https://github.com/pry/pry/pull/1281 is merged.
This makes https://github.com/pry/pry/pull/1278 unnecessary.
2014-08-10 17:37:21 -06:00

415 lines
12 KiB
Ruby

require_relative 'helper'
describe Pry do
before do
@str_output = StringIO.new
end
describe "Exotic object support" do
# regression test for exotic object support
it "Should not error when return value is a BasicObject instance" do
ReplTester.start do
input('BasicObject.new').should =~ /^=> #<BasicObject:/
end
end
end
describe 'DISABLE_PRY' do
before do
ENV['DISABLE_PRY'] = 'true'
end
after do
ENV.delete 'DISABLE_PRY'
end
it 'should not binding.pry' do
binding.pry.should == nil
end
it 'should not Pry.start' do
Pry.start.should == nil
end
end
describe "Pry.critical_section" do
it "should prevent Pry being called" do
output = StringIO.new
Pry.config.output = output
Pry.critical_section do
Pry.start
end
output.string.should =~ /Pry started inside Pry/
end
end
describe "Pry.binding_for" do
# regression test for burg's bug (see git history)
it "Should not error when object doesn't have a valid == method" do
o = Object.new
def o.==(other)
raise
end
expect { Pry.binding_for(o) }.to_not raise_error
end
it "should not leak local variables" do
[Object.new, Array, 3].each do |obj|
Pry.binding_for(obj).eval("local_variables").should be_empty
end
end
it "should work on frozen objects" do
a = "hello".freeze
Pry.binding_for(a).eval("self").should.equal? a
end
end
describe "#last_exception=" do
before do
@pry = Pry.new binding: binding
@e = mock_exception "foo.rb:1"
end
it "returns an instance of Pry::LastException" do
@pry.last_exception = @e
@pry.last_exception.wrapped_exception.should == @e
end
it "returns a frozen exception" do
@pry.last_exception = @e.freeze
expect(@pry.last_exception).to be_frozen
end
it "returns an object who mirrors itself as the wrapped exception" do
@pry.last_exception = @e.freeze
expect(@pry.last_exception).to be_an_instance_of StandardError
end
end
describe "open a Pry session on an object" do
describe "rep" do
before do
class Hello
end
end
after do
Object.send(:remove_const, :Hello)
end
# bug fix for https://github.com/banister/pry/issues/93
it 'should not leak pry constants into Object namespace' do
expect { pry_eval(Object.new, "Command") }.to raise_error
end
it 'should be able to operate inside the BasicObject class' do
pry_eval(BasicObject, ":foo", "Pad.obj = _")
Pad.obj.should == :foo
end
it 'should set an ivar on an object' do
o = Object.new
pry_eval(o, "@x = 10")
o.instance_variable_get(:@x).should == 10
end
it 'should display error if Pry instance runs out of input' do
redirect_pry_io(StringIO.new, @str_output) do
Pry.start
end
@str_output.string.should =~ /Error: Pry ran out of things to read/
end
it 'should make self evaluate to the receiver of the rep session' do
o = :john
pry_eval(o, "self").should == o
end
it 'should define a nested class under Hello and not on top-level or Pry' do
mock_pry(Pry.binding_for(Hello), "class Nested", "end")
Hello.const_defined?(:Nested).should == true
end
it 'should suppress output if input ends in a ";" and is an Exception object (single line)' do
mock_pry("Exception.new;").should == ""
end
it 'should suppress output if input ends in a ";" (single line)' do
mock_pry("x = 5;").should == ""
end
it 'should be able to evaluate exceptions normally' do
was_called = false
mock_pry("RuntimeError.new", :exception_handler => proc{ was_called = true })
was_called.should == false
end
it 'should notice when exceptions are raised' do
was_called = false
mock_pry("raise RuntimeError", :exception_handler => proc{ was_called = true })
was_called.should == true
end
it 'should not try to catch intended exceptions' do
expect { mock_pry("raise SystemExit") }.to raise_error SystemExit
# SIGTERM
expect { mock_pry("raise SignalException.new(15)") }.to raise_error SignalException
end
describe "multi-line input" do
it "works" do
mock_pry('x = ', '1 + 4').should =~ /5/
end
it 'should suppress output if input ends in a ";" (multi-line)' do
mock_pry('def self.blah', ':test', 'end;').should == ''
end
describe "newline stripping from an empty string" do
it "with double quotes" do
mock_pry('"', '"').should =~ %r|"\\n"|
mock_pry('"', "\n", "\n", "\n", '"').should =~ %r|"\\n\\n\\n\\n"|
end
it "with single quotes" do
mock_pry("'", "'").should =~ %r|"\\n"|
mock_pry("'", "\n", "\n", "\n", "'").should =~ %r|"\\n\\n\\n\\n"|
end
it "with fancy delimiters" do
mock_pry('%(', ')').should =~ %r|"\\n"|
mock_pry('%|', "\n", "\n", '|').should =~ %r|"\\n\\n\\n"|
mock_pry('%q[', "\n", "\n", ']').should =~ %r|"\\n\\n\\n"|
end
end
describe "newline stripping from an empty regexp" do
it "with regular regexp delimiters" do
mock_pry('/', '/').should =~ %r{/\n/}
end
it "with fancy delimiters" do
mock_pry('%r{', "\n", "\n", '}').should =~ %r{/\n\n\n/}
mock_pry('%r<', "\n", '>').should =~ %r{/\n\n/}
end
end
describe "newline from an empty heredoc" do
it "works" do
mock_pry('<<HERE', 'HERE').should =~ %r|""|
mock_pry("<<'HERE'", "\n", 'HERE').should =~ %r|"\\n"|
mock_pry("<<-'HERE'", "\n", "\n", 'HERE').should =~ %r|"\\n\\n"|
end
end
end
end
describe "repl" do
describe "basic functionality" do
it 'should set an ivar on an object and exit the repl' do
input_strings = ["@x = 10", "exit-all"]
input = InputTester.new(*input_strings)
o = Object.new
pry_tester = Pry.start(o, :input => input, :output => StringIO.new)
o.instance_variable_get(:@x).should == 10
end
end
describe "complete_expression?" do
it "should not mutate the input!" do
clean = "puts <<-FOO\nhi\nFOO\n"
a = clean.dup
Pry::Code.complete_expression?(a)
a.should == clean
end
end
describe "history arrays" do
it 'sets _ to the last result' do
t = pry_tester
t.eval ":foo"
t.eval("_").should == :foo
t.eval "42"
t.eval("_").should == 42
end
it 'sets out to an array with the result' do
t = pry_tester
t.eval ":foo"
t.eval "42"
res = t.eval "_out_"
res.should be_a_kind_of Pry::HistoryArray
res[1..2].should == [:foo, 42]
end
it 'sets _in_ to an array with the entered lines' do
t = pry_tester
t.eval ":foo"
t.eval "42"
res = t.eval "_in_"
res.should be_a_kind_of Pry::HistoryArray
res[1..2].should == [":foo\n", "42\n"]
end
it 'uses 100 as the size of _in_ and _out_' do
pry_tester.eval("[_in_.max_size, _out_.max_size]").should == [100, 100]
end
it 'can change the size of the history arrays' do
pry_tester(:memory_size => 1000).eval("[_out_, _in_].map(&:max_size)").should == [1000, 1000]
end
it 'store exceptions' do
mock_pry("foo!", "Pad.in = _in_[-1]; Pad.out = _out_[-1]")
Pad.in.should == "foo!\n"
expect(Pad.out).to be_a_kind_of NoMethodError
end
end
describe "last_result" do
it "should be set to the most recent value" do
pry_eval("2", "_ + 82").should == 84
end
# This test needs mock_pry because the command retvals work by
# replacing the eval_string, so _ won't be modified without Pry doing
# a REPL loop.
it "should be set to the result of a command with :keep_retval" do
Pry::Commands.block_command '++', '', :keep_retval => true do |a|
a.to_i + 1
end
mock_pry('++ 86', '++ #{_}').should =~ /88/
end
it "should be preserved over an empty line" do
pry_eval("2 + 2", " ", "\t", " ", "_ + 92").should == 96
end
it "should be preserved when evalling a command without :keep_retval" do
pry_eval("2 + 2", "ls -l", "_ + 96").should == 100
end
end
describe "nesting" do
after do
Pry.reset_defaults
Pry.config.color = false
end
it 'should nest properly' do
Pry.config.input = InputTester.new("cd 1", "cd 2", "cd 3", "\"nest:\#\{(_pry_.binding_stack.size - 1)\}\"", "exit-all")
Pry.config.output = @str_output
o = Object.new
pry_tester = o.pry
@str_output.string.should =~ /nest:3/
end
end
describe "defining methods" do
it 'should define a method on the singleton class of an object when performing "def meth;end" inside the object' do
[Object.new, {}, []].each do |val|
pry_eval(val, 'def hello; end')
val.methods(false).map(&:to_sym).include?(:hello).should == true
end
end
it 'should define an instance method on the module when performing "def meth;end" inside the module' do
hello = Module.new
pry_eval(hello, "def hello; end")
hello.instance_methods(false).map(&:to_sym).include?(:hello).should == true
end
it 'should define an instance method on the class when performing "def meth;end" inside the class' do
hello = Class.new
pry_eval(hello, "def hello; end")
hello.instance_methods(false).map(&:to_sym).include?(:hello).should == true
end
it 'should define a method on the class of an object when performing "def meth;end" inside an immediate value or Numeric' do
[:test, 0, true, false, nil,
(0.0 unless Pry::Helpers::BaseHelpers.jruby?)].each do |val|
pry_eval(val, "def hello; end");
val.class.instance_methods(false).map(&:to_sym).include?(:hello).should == true
end
end
end
describe "Object#pry" do
after do
Pry.reset_defaults
Pry.config.color = false
end
it "should start a pry session on the receiver (first form)" do
Pry.config.input = InputTester.new("self", "exit-all")
str_output = StringIO.new
Pry.config.output = str_output
20.pry
str_output.string.should =~ /20/
end
it "should start a pry session on the receiver (second form)" do
Pry.config.input = InputTester.new("self", "exit-all")
str_output = StringIO.new
Pry.config.output = str_output
pry 20
str_output.string.should =~ /20/
end
it "should raise if more than two arguments are passed to Object#pry" do
expect { pry(20, :quiet, :input => Readline) }.to raise_error ArgumentError
end
end
describe "Pry.binding_for" do
it 'should return TOPLEVEL_BINDING if parameter self is main' do
_main_ = lambda { TOPLEVEL_BINDING.eval('self') }
Pry.binding_for(_main_.call).is_a?(Binding).should == true
Pry.binding_for(_main_.call).should == TOPLEVEL_BINDING
Pry.binding_for(_main_.call).should == Pry.binding_for(_main_.call)
end
end
end
end
describe 'setting custom options' do
it 'does not raise for unrecognized options' do
expect { instance = Pry.new(:custom_option => 'custom value') }.to_not raise_error
end
it 'correctly handles the :quiet option (#1261)' do
instance = Pry.new(:quiet => true)
instance.quiet?.should == true
end
end
describe "a fresh instance" do
it "should use `caller` as its backtrace" do
location = "#{__FILE__}:#{__LINE__ + 1}"[1..-1] # omit leading .
backtrace = Pry.new.backtrace
backtrace.should_not equal nil
backtrace.any? { |l| l.include?(location) }.should equal true
end
end
end