require 'spec_helper' describe "expect(...).to be_predicate" do it "passes when actual returns true for :predicate?" do actual = double("actual", :happy? => true) expect(actual).to be_happy end it "passes when actual returns true for :predicates? (present tense)" do actual = double("actual", :exists? => true, :exist? => true) expect(actual).to be_exist end it "fails when actual returns false for :predicate?" do actual = double("actual", :happy? => false) expect { expect(actual).to be_happy }.to fail_with("expected happy? to return true, got false") end it "fails when actual returns false for :predicate?" do actual = double("actual", :happy? => nil) expect { expect(actual).to be_happy }.to fail_with("expected happy? to return true, got nil") end it "fails when actual does not respond to :predicate?" do expect { expect(Object.new).to be_happy }.to raise_error(NameError, /happy\?/) end it 'warns of deprecation when :predicate? is private' do privately_happy = Class.new do private def happy? true end end allow(RSpec).to receive(:deprecate) expect(RSpec).to receive(:deprecate).with( "matching with be_happy on private method happy?", :replacement => "`expect(object.send(:happy?)).to be_true` or change the method's visibility to public", :call_site => RSpec::Mocks::ArgumentMatchers::RegexpMatcher.new(/#{__FILE__}:#{__LINE__ + 2}/) ) expect(privately_happy.new).to be_happy end it "fails on error other than NameError" do actual = double("actual") actual.should_receive(:foo?).and_raise("aaaah") expect { expect(actual).to be_foo }.to raise_error(/aaaah/) end it "fails on error other than NameError (with the present tense predicate)" do actual = Object.new actual.should_receive(:foos?).and_raise("aaaah") expect { expect(actual).to be_foo }.to raise_error(/aaaah/) end it "does not support operator chaining like a basic `be` matcher does" do matcher = be_happy value = double(:happy? => false) expect(matcher == value).to be false end it 'warns of deprecation when actual does not respond to :predicate?' do oddly_happy_class = Class.new do def method_missing(method) return true if method == :happy? end end expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /Matching with be_happy on an object that doesn't respond to `happy\?`/) expect(oddly_happy_class.new).to be_happy end it 'does not warn of deprecation when actual responds to present tense predicate' do present_happy_class = Class.new do def exists? true end end expect_no_deprecation expect(present_happy_class.new).to be_exist end end describe "expect(...).not_to be_predicate" do it "passes when actual returns false for :sym?" do actual = double("actual", :happy? => false) expect(actual).not_to be_happy end it "passes when actual returns nil for :sym?" do actual = double("actual", :happy? => nil) expect(actual).not_to be_happy end it "fails when actual returns true for :sym?" do actual = double("actual", :happy? => true) expect { expect(actual).not_to be_happy }.to fail_with("expected happy? to return false, got true") end it "fails when actual does not respond to :sym?" do expect { expect(Object.new).not_to be_happy }.to raise_error(NameError) end end describe "expect(...).to be_predicate(*args)" do it "passes when actual returns true for :predicate?(*args)" do actual = double("actual") actual.should_receive(:older_than?).with(3).and_return(true) expect(actual).to be_older_than(3) end it "fails when actual returns false for :predicate?(*args)" do actual = double("actual") actual.should_receive(:older_than?).with(3).and_return(false) expect { expect(actual).to be_older_than(3) }.to fail_with("expected older_than?(3) to return true, got false") end it "fails when actual does not respond to :predicate?" do expect { expect(Object.new).to be_older_than(3) }.to raise_error(NameError) end end describe "expect(...).not_to be_predicate(*args)" do it "passes when actual returns false for :predicate?(*args)" do actual = double("actual") actual.should_receive(:older_than?).with(3).and_return(false) expect(actual).not_to be_older_than(3) end it "fails when actual returns true for :predicate?(*args)" do actual = double("actual") actual.should_receive(:older_than?).with(3).and_return(true) expect { expect(actual).not_to be_older_than(3) }.to fail_with("expected older_than?(3) to return false, got true") end it "fails when actual does not respond to :predicate?" do expect { expect(Object.new).not_to be_older_than(3) }.to raise_error(NameError) end end describe "expect(...).to be_predicate(&block)" do it "passes when actual returns true for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:happy?).and_yield delegate.should_receive(:check_happy).and_return(true) expect(actual).to be_happy { delegate.check_happy } end it "fails when actual returns false for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:happy?).and_yield delegate.should_receive(:check_happy).and_return(false) expect { expect(actual).to be_happy { delegate.check_happy } }.to fail_with("expected happy? to return true, got false") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_happy => true) expect { expect(Object.new).to be_happy { delegate.check_happy } }.to raise_error(NameError) end end describe "expect(...).not_to be_predicate(&block)" do it "passes when actual returns false for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:happy?).and_yield delegate.should_receive(:check_happy).and_return(false) expect(actual).not_to be_happy { delegate.check_happy } end it "fails when actual returns true for :predicate?(&block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:happy?).and_yield delegate.should_receive(:check_happy).and_return(true) expect { expect(actual).not_to be_happy { delegate.check_happy } }.to fail_with("expected happy? to return false, got true") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_happy => true) expect { expect(Object.new).not_to be_happy { delegate.check_happy } }.to raise_error(NameError) end end describe "expect(...).to be_predicate(*args, &block)" do it "passes when actual returns true for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:older_than?).with(3).and_yield(3) delegate.should_receive(:check_older_than).with(3).and_return(true) expect(actual).to be_older_than(3) { |age| delegate.check_older_than(age) } end it "fails when actual returns false for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:older_than?).with(3).and_yield(3) delegate.should_receive(:check_older_than).with(3).and_return(false) expect { expect(actual).to be_older_than(3) { |age| delegate.check_older_than(age) } }.to fail_with("expected older_than?(3) to return true, got false") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_older_than => true) expect { expect(Object.new).to be_older_than(3) { |age| delegate.check_older_than(age) } }.to raise_error(NameError) end end describe "expect(...).not_to be_predicate(*args, &block)" do it "passes when actual returns false for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:older_than?).with(3).and_yield(3) delegate.should_receive(:check_older_than).with(3).and_return(false) expect(actual).not_to be_older_than(3) { |age| delegate.check_older_than(age) } end it "fails when actual returns true for :predicate?(*args, &block)" do actual = double("actual") delegate = double("delegate") actual.should_receive(:older_than?).with(3).and_yield(3) delegate.should_receive(:check_older_than).with(3).and_return(true) expect { expect(actual).not_to be_older_than(3) { |age| delegate.check_older_than(age) } }.to fail_with("expected older_than?(3) to return false, got true") end it "fails when actual does not respond to :predicate?" do delegate = double("delegate", :check_older_than => true) expect { expect(Object.new).not_to be_older_than(3) { |age| delegate.check_older_than(age) } }.to raise_error(NameError) end end describe "expect(...).to be_truthy" do it "passes when actual equal?(true)" do expect(true).to be_truthy end it "passes when actual is 1" do expect(1).to be_truthy end it "fails when actual equal?(false)" do expect { expect(false).to be_truthy }.to fail_with("expected: truthy value\n got: false") end end describe "expect(...).to be_false" do it "is deprecated" do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /be_false/) expect(false).to be_false end it "has the correct call site in the deprecation message" do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) expect(false).to be_false end it "still passes" do allow(RSpec).to receive(:deprecate) expect(false).to be_false end it "still fails" do allow(RSpec).to receive(:deprecate) expect { expect(true).to be_false }.to fail_with(/expected: falsey value/) end end describe "expect(...).to be_true" do it "is deprecated" do expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /be_true/) expect(true).to be_true end it "still passes" do allow(RSpec).to receive(:deprecate) expect(true).to be_true end it "still fails" do allow(RSpec).to receive(:deprecate) expect { expect(false).to be_true }.to fail_with(/expected: truthy value/) end end describe "expect(...).to be_falsey" do it "passes when actual equal?(false)" do expect(false).to be_falsey end it "passes when actual equal?(nil)" do expect(nil).to be_falsey end it "fails when actual equal?(true)" do expect { expect(true).to be_falsey }.to fail_with("expected: falsey value\n got: true") end end describe "expect(...).to be_falsy" do it "passes when actual equal?(false)" do expect(false).to be_falsy end it "passes when actual equal?(nil)" do expect(nil).to be_falsy end it "fails when actual equal?(true)" do expect { expect(true).to be_falsy }.to fail_with("expected: falsey value\n got: true") end end describe "expect(...).to be_nil" do it "passes when actual is nil" do expect(nil).to be_nil end it "fails when actual is not nil" do expect { expect(:not_nil).to be_nil }.to fail_with(/^expected: nil/) end end describe "expect(...).not_to be_nil" do it "passes when actual is not nil" do expect(:not_nil).not_to be_nil end it "fails when actual is nil" do expect { expect(nil).not_to be_nil }.to fail_with(/^expected: not nil/) end end describe "expect(...).to be <" do it "passes when < operator returns true" do expect(3).to be < 4 end it "fails when < operator returns false" do expect { expect(3).to be < 3 }.to fail_with("expected: < 3\n got: 3") end it "describes itself" do expect(be.<(4).description).to eq "be < 4" end end describe "expect(...).to be <=" do it "passes when <= operator returns true" do expect(3).to be <= 4 expect(4).to be <= 4 end it "fails when <= operator returns false" do expect { expect(3).to be <= 2 }.to fail_with("expected: <= 2\n got: 3") end end describe "expect(...).to be >=" do it "passes when >= operator returns true" do expect(4).to be >= 4 expect(5).to be >= 4 end it "fails when >= operator returns false" do expect { expect(3).to be >= 4 }.to fail_with("expected: >= 4\n got: 3") end end describe "expect(...).to be >" do it "passes when > operator returns true" do expect(5).to be > 4 end it "fails when > operator returns false" do expect { expect(3).to be > 4 }.to fail_with("expected: > 4\n got: 3") end end describe "expect(...).to be ==" do it "passes when == operator returns true" do expect(5).to be == 5 end it "fails when == operator returns false" do expect { expect(3).to be == 4 }.to fail_with("expected: == 4\n got: 3") end it 'works when the target overrides `#send`' do klass = Struct.new(:message) do def send :message_sent end end msg_1 = klass.new("hello") msg_2 = klass.new("hello") expect(msg_1).to be == msg_2 end end describe "expect(...).to be =~" do it "passes when =~ operator returns true" do expect("a string").to be =~ /str/ end it "fails when =~ operator returns false" do expect { expect("a string").to be =~ /blah/ }.to fail_with(%Q|expected: =~ /blah/\n got: "a string"|) end end describe "should be =~", :uses_should do it "passes when =~ operator returns true" do "a string".should be =~ /str/ end it "fails when =~ operator returns false" do expect { "a string".should be =~ /blah/ }.to fail_with(%Q|expected: =~ /blah/\n got: "a string"|) end end describe "expect(...).to be ===" do it "passes when === operator returns true" do expect(Hash).to be === Hash.new end it "fails when === operator returns false" do expect { expect(Hash).to be === "not a hash" }.to fail_with(%[expected: === "not a hash"\n got: Hash]) end end describe "expect(...).not_to with operators" do it "coaches user to stop using operators with expect().not_to" do expect { expect(5).not_to be < 6 }.to raise_error(/`expect\(actual\).not_to be < 6` not only FAILED,\nit is a bit confusing./m) end end describe "should_not with operators", :uses_only_should do it "coaches user to stop using operators with should_not" do lambda { 5.should_not be < 6 }.should raise_error(/`actual.should_not be < 6` not only FAILED,\nit is a bit confusing./m) end end describe "expect(...).to be" do it "passes if actual is truthy" do expect(true).to be expect(1).to be end it "fails if actual is false" do expect { expect(false).to be }.to fail_with("expected false to evaluate to true") end it "fails if actual is nil" do expect { expect(nil).to be }.to fail_with("expected nil to evaluate to true") end it "describes itself" do expect(be.description).to eq "be" end end describe "expect(...).not_to be" do it "passes if actual is falsy" do expect(false).not_to be expect(nil).not_to be end it "fails on true" do expect { expect(true).not_to be }.to fail_with("expected true to evaluate to false") end end describe "expect(...).to be(value)" do it "delegates to equal" do matcher = equal(5) self.should_receive(:equal).with(5).and_return(matcher) expect(5).to be(5) end end describe "expect(...).not_to be(value)" do it "delegates to equal" do matcher = equal(4) self.should_receive(:equal).with(4).and_return(matcher) expect(5).not_to be(4) end end describe "'expect(...).to be' with operator" do it "includes 'be' in the description" do expect((be > 6).description).to match(/be > 6/) expect((be >= 6).description).to match(/be >= 6/) expect((be <= 6).description).to match(/be <= 6/) expect((be < 6).description).to match(/be < 6/) end end describe "arbitrary predicate with DelegateClass" do it "accesses methods defined in the delegating class (LH[#48])" do require 'delegate' class ArrayDelegate < DelegateClass(Array) def initialize(array) @internal_array = array super(@internal_array) end def large? @internal_array.size >= 5 end end delegate = ArrayDelegate.new([1,2,3,4,5,6]) expect(delegate).to be_large end end describe "be_a, be_an" do it "passes when class matches" do expect("foobar").to be_a(String) expect([1,2,3]).to be_an(Array) end it "fails when class does not match" do expect("foobar").not_to be_a(Hash) expect([1,2,3]).not_to be_an(Integer) end end describe "be_an_instance_of" do it "passes when direct class matches" do expect(5).to be_an_instance_of(Fixnum) end it "fails when class is higher up hierarchy" do expect(5).not_to be_an_instance_of(Numeric) end end