describe "Kernel#try" do

  it "should return the value of the 1st lambda/proc/method call if the 1st proc succeeds" do
    try(
      Proc.new { 'foo' },
      Proc.new { 'bar' }
    ).should == 'foo'
  end

  it "should return the value of the 2nd lambda/proc/method call if the 1st fails but the 2nd succeeds" do
    try(
      Proc.new { raise StandardError },
      Proc.new { 1 + 1 }
    ).should == 2
  end

  it "should accept an arbitrary number of arguments and return the value of the last proc if only the last proc succeeds" do
    try(
      Proc.new { raise StandardError },
      Kernel.method('raise'),
      lambda { raise RuntimeError },
      proc { 'last' }
    ).should == 'last'
  end

  it "should allow a fallback value to be passed as the final value" do
    value = try(
      Proc.new { raise StandardError },
      Proc.new { raise StandardError },
      :fallback
    )
    value.should == :fallback
  end

  it "should accept Methods" do
    to_s_of_1_method = 1.method('to_s')
    to_s_of_foo_method = 'foo'.method('to_s')
    try(
      to_s_of_1_method,
      to_s_of_foo_method
    ).should == '1'
  end

  it "should accept procs" do
    test_proc = proc { 1 + 1 }
    try(
      test_proc,
      proc { 'will not come here' }
    ).should == 2
  end

  it "should accept lambdas" do
    try(
      lambda { 1 + 1 },
      lambda { 2 + 2 }
    ).should == 2
  end

  it "should raise a RuntimeError if none of the procs succeed" do
    lambda {
      try(
        Proc.new { raise StandardError },
        Proc.new { raise StandardError }
      )
    }.should raise_error(RuntimeError, 'None of the given procs succeeded')
  end

  it "should raise an ArgumentError if passed less than 2 arguments" do
    lambda {
      try()
    }.should raise_error(ArgumentError, 'try requires at least 2 arguments')

    lambda {
      try(Proc.new {})
    }.should raise_error(ArgumentError, 'try requires at least 2 arguments')
  end
end