Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Ensure #== is defined on build in matchers so that they can be composed.

For example:

expect {
  user.emailed!
}.to change{user.last_emailed_at}.from(nil).to be_within(1.second).of(Time.zone.now)

Closes #161.
  • Loading branch information...
commit d427bac95e17046aadf7f4a4c65b544dacd9f34e 1 parent c897a47
@myronmarston myronmarston authored
Showing with 135 additions and 0 deletions.
  1. +1 −0  lib/rspec/matchers/built_in/be_within.rb
  2. +1 −0  lib/rspec/matchers/built_in/change.rb
  3. +1 −0  lib/rspec/matchers/built_in/has.rb
  4. +1 −0  lib/rspec/matchers/built_in/have.rb
  5. +1 −0  lib/rspec/matchers/built_in/raise_error.rb
  6. +1 −0  lib/rspec/matchers/built_in/respond_to.rb
  7. +1 −0  lib/rspec/matchers/built_in/satisfy.rb
  8. +1 −0  lib/rspec/matchers/built_in/throw_symbol.rb
  9. +2 −0  lib/rspec/matchers/built_in/yield.rb
  10. +4 −0 spec/rspec/matchers/be_instance_of_spec.rb
  11. +4 −0 spec/rspec/matchers/be_kind_of_spec.rb
  12. +4 −0 spec/rspec/matchers/be_within_spec.rb
  13. +6 −0 spec/rspec/matchers/change_spec.rb
  14. +4 −0 spec/rspec/matchers/cover_spec.rb
  15. +4 −0 spec/rspec/matchers/eq_spec.rb
  16. +4 −0 spec/rspec/matchers/eql_spec.rb
  17. +3 −0  spec/rspec/matchers/equal_spec.rb
  18. +6 −0 spec/rspec/matchers/exist_spec.rb
  19. +5 −0 spec/rspec/matchers/has_spec.rb
  20. +3 −0  spec/rspec/matchers/have_spec.rb
  21. +4 −0 spec/rspec/matchers/include_spec.rb
  22. +4 −0 spec/rspec/matchers/match_array_spec.rb
  23. +4 −0 spec/rspec/matchers/match_spec.rb
  24. +5 −0 spec/rspec/matchers/raise_error_spec.rb
  25. +3 −0  spec/rspec/matchers/respond_to_spec.rb
  26. +4 −0 spec/rspec/matchers/satisfy_spec.rb
  27. +8 −0 spec/rspec/matchers/start_with_end_with_spec.rb
  28. +5 −0 spec/rspec/matchers/throw_symbol_spec.rb
  29. +28 −0 spec/rspec/matchers/yield_spec.rb
  30. +13 −0 spec/support/shared_examples.rb
View
1  lib/rspec/matchers/built_in/be_within.rb
@@ -12,6 +12,7 @@ def matches?(actual)
raise needs_subtractable unless @actual.respond_to? :-
(@actual - @expected).abs <= @delta
end
+ alias == matches?
def of(expected)
@expected = expected
View
1  lib/rspec/matchers/built_in/change.rb
@@ -18,6 +18,7 @@ def matches?(event_proc)
(!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
end
+ alias == matches?
def raise_block_syntax_error
raise SyntaxError.new(<<-MESSAGE)
View
1  lib/rspec/matchers/built_in/has.rb
@@ -9,6 +9,7 @@ def initialize(expected, *args)
def matches?(actual)
actual.__send__(predicate(@expected), *@args)
end
+ alias == matches?
def failure_message_for_should
"expected ##{predicate(@expected)}#{failure_message_args_description} to return true, got false"
View
1  lib/rspec/matchers/built_in/have.rb
@@ -31,6 +31,7 @@ def matches?(collection_or_owner)
else @actual == @expected
end
end
+ alias == matches?
def determine_collection(collection_or_owner)
if collection_or_owner.respond_to?(@collection_name)
View
1  lib/rspec/matchers/built_in/raise_error.rb
@@ -35,6 +35,7 @@ def matches?(given_proc, negative_expectation = false)
ensure
return (@raised_expected_error & @with_expected_message) ? (@eval_block ? @eval_block_passed : true) : false
end
+ alias == matches?
def does_not_match?(given_proc)
!matches?(given_proc, :negative_expectation)
View
1  lib/rspec/matchers/built_in/respond_to.rb
@@ -10,6 +10,7 @@ def initialize(*names)
def matches?(actual)
find_failing_method_names(actual, :reject).empty?
end
+ alias == matches?
def does_not_match?(actual)
find_failing_method_names(actual, :select).empty?
View
1  lib/rspec/matchers/built_in/satisfy.rb
@@ -11,6 +11,7 @@ def matches?(actual, &block)
@actual = actual
@block.call(actual)
end
+ alias == matches?
def failure_message_for_should
"expected #{@actual} to satisfy block"
View
1  lib/rspec/matchers/built_in/throw_symbol.rb
@@ -51,6 +51,7 @@ def matches?(given_proc)
end
end
end
+ alias == matches?
def failure_message_for_should
"expected #{expected} to be thrown, got #{caught}"
View
2  lib/rspec/matchers/built_in/yield.rb
@@ -115,6 +115,7 @@ def matches?(block)
@actual = @probe.single_yield_args
@probe.yielded_once?(:yield_with_args) && args_match?
end
+ alias == matches?
def failure_message_for_should
"expected given block to yield with arguments, but #{positive_failure_reason}"
@@ -184,6 +185,7 @@ def matches?(block)
@actual = @probe.successive_yield_args
args_match?
end
+ alias == matches?
def failure_message_for_should
"expected given block to yield successively with arguments, but yielded with unexpected arguments" +
View
4 spec/rspec/matchers/be_instance_of_spec.rb
@@ -4,6 +4,10 @@ module RSpec
module Matchers
[:be_an_instance_of, :be_instance_of].each do |method|
describe "actual.should #{method}(expected)" do
+ it_behaves_like "an RSpec matcher", :valid_value => 5, :invalid_value => "a" do
+ let(:matcher) { send(method, Fixnum) }
+ end
+
it "passes if actual is instance of expected class" do
5.should send(method, Fixnum)
end
View
4 spec/rspec/matchers/be_kind_of_spec.rb
@@ -4,6 +4,10 @@ module RSpec
module Matchers
[:be_a_kind_of, :be_kind_of].each do |method|
describe "actual.should #{method}(expected)" do
+ it_behaves_like "an RSpec matcher", :valid_value => 5, :invalid_value => "a" do
+ let(:matcher) { send(method, Fixnum) }
+ end
+
it "passes if actual is instance of expected class" do
5.should send(method, Fixnum)
end
View
4 spec/rspec/matchers/be_within_spec.rb
@@ -3,6 +3,10 @@
module RSpec
module Matchers
describe "[actual.should] be_within(delta).of(expected)" do
+ it_behaves_like "an RSpec matcher", :valid_value => 5, :invalid_value => -5 do
+ let(:matcher) { be_within(2).of(4.0) }
+ end
+
it "matches when actual == expected" do
be_within(0.5).of(5.0).matches?(5.0).should be_true
end
View
6 spec/rspec/matchers/change_spec.rb
@@ -153,6 +153,12 @@ def ==(other)
end
describe "should change { block }" do
+ o = SomethingExpected.new
+ it_behaves_like "an RSpec matcher", :valid_value => lambda { o.some_value = 5 },
+ :invalid_value => lambda { } do
+ let(:matcher) { change { o.some_value } }
+ end
+
before(:each) do
@instance = SomethingExpected.new
@instance.some_value = 5
View
4 spec/rspec/matchers/cover_spec.rb
@@ -2,6 +2,10 @@
if (1..2).respond_to?(:cover?)
describe "should cover(expected)" do
+ it_behaves_like "an RSpec matcher", :valid_value => (1..10), :invalid_value => (20..30) do
+ let(:matcher) { cover(5) }
+ end
+
context "for a range target" do
it "passes if target covers expected" do
(1..10).should cover(5)
View
4 spec/rspec/matchers/eq_spec.rb
@@ -3,6 +3,10 @@
module RSpec
module Matchers
describe "eq" do
+ it_behaves_like "an RSpec matcher", :valid_value => 1, :invalid_value => 2 do
+ let(:matcher) { eq(1) }
+ end
+
it "is diffable" do
eq(1).should be_diffable
end
View
4 spec/rspec/matchers/eql_spec.rb
@@ -3,6 +3,10 @@
module RSpec
module Matchers
describe "eql" do
+ it_behaves_like "an RSpec matcher", :valid_value => 1, :invalid_value => 2 do
+ let(:matcher) { eql(1) }
+ end
+
it "is diffable" do
eql(1).should be_diffable
end
View
3  spec/rspec/matchers/equal_spec.rb
@@ -2,6 +2,9 @@
module RSpec
module Matchers
describe "equal" do
+ it_behaves_like "an RSpec matcher", :valid_value => :a, :invalid_value => :b do
+ let(:matcher) { equal(:a) }
+ end
def inspect_object(o)
"#<#{o.class}:#{o.object_id}> => #{o.inspect}"
View
6 spec/rspec/matchers/exist_spec.rb
@@ -1,6 +1,12 @@
require 'spec_helper'
+require 'ostruct'
describe "exist matcher" do
+ it_behaves_like "an RSpec matcher", :valid_value => OpenStruct.new(:exist? => true),
+ :invalid_value => OpenStruct.new(:exist? => false) do
+ let(:matcher) { exist }
+ end
+
context "when the object does not respond to #exist? or #exists?" do
subject { mock }
View
5 spec/rspec/matchers/has_spec.rb
@@ -1,6 +1,11 @@
require 'spec_helper'
describe "should have_sym(*args)" do
+ it_behaves_like "an RSpec matcher", :valid_value => { :a => 1 },
+ :invalid_value => {} do
+ let(:matcher) { have_key(:a) }
+ end
+
it "passes if #has_sym?(*args) returns true" do
{:a => "A"}.should have_key(:a)
end
View
3  spec/rspec/matchers/have_spec.rb
@@ -29,6 +29,9 @@ def create_collection_owner_with(n)
end
describe "should have(n).items" do
+ it_behaves_like "an RSpec matcher", :valid_value => [1, 2], :invalid_value => [1] do
+ let(:matcher) { have(2).items }
+ end
it "passes if target has a collection of items with n members" do
owner = create_collection_owner_with(3)
View
4 spec/rspec/matchers/include_spec.rb
@@ -6,6 +6,10 @@
end
describe "should include(with_one_arg)" do
+ it_behaves_like "an RSpec matcher", :valid_value => [1, 2], :invalid_value => [1] do
+ let(:matcher) { include(2) }
+ end
+
context "for a string target" do
it "passes if target includes expected" do
"abc".should include("a")
View
4 spec/rspec/matchers/match_array_spec.rb
@@ -15,6 +15,10 @@ def ==(other)
end
describe "using match_array with expect" do
+ it_behaves_like "an RSpec matcher", :valid_value => [1, 2], :invalid_value => [1] do
+ let(:matcher) { match_array([2, 1]) }
+ end
+
it "passes a valid positive expectation" do
expect([1, 2]).to match_array [2, 1]
end
View
4 spec/rspec/matchers/match_spec.rb
@@ -1,6 +1,10 @@
require 'spec_helper'
describe "should match(expected)" do
+ it_behaves_like "an RSpec matcher", :valid_value => 'ab', :invalid_value => 'bc' do
+ let(:matcher) { match(/a/) }
+ end
+
it "passes when target (String) matches expected (Regexp)" do
"string".should match(/tri/)
end
View
5 spec/rspec/matchers/raise_error_spec.rb
@@ -1,6 +1,11 @@
require 'spec_helper'
describe "should raise_error" do
+ it_behaves_like("an RSpec matcher", :valid_value => lambda { raise "boom" },
+ :invalid_value => lambda { }) do
+ let(:matcher) { raise_error(/boom/) }
+ end
+
it "passes if anything is raised" do
lambda {raise}.should raise_error
end
View
3  spec/rspec/matchers/respond_to_spec.rb
@@ -1,6 +1,9 @@
require 'spec_helper'
describe "should respond_to(:sym)" do
+ it_behaves_like "an RSpec matcher", :valid_value => "s", :invalid_value => 5 do
+ let(:matcher) { respond_to(:upcase) }
+ end
it "passes if target responds to :sym" do
Object.new.should respond_to(:methods)
View
4 spec/rspec/matchers/satisfy_spec.rb
@@ -1,6 +1,10 @@
require 'spec_helper'
describe "should satisfy { block }" do
+ it_behaves_like "an RSpec matcher", :valid_value => true, :invalid_value => false do
+ let(:matcher) { satisfy { |v| v } }
+ end
+
it "describes itself" do
satisfy.description.should eq("satisfy block")
end
View
8 spec/rspec/matchers/start_with_end_with_spec.rb
@@ -1,6 +1,10 @@
require "spec_helper"
describe "should start_with" do
+ it_behaves_like "an RSpec matcher", :valid_value => "ab", :invalid_value => "bc" do
+ let(:matcher) { start_with("a") }
+ end
+
context "with a string" do
it "passes if it matches the start of the actual string" do
"this string".should start_with "this str"
@@ -87,6 +91,10 @@
end
describe "should end_with" do
+ it_behaves_like "an RSpec matcher", :valid_value => "ab", :invalid_value => "bc" do
+ let(:matcher) { end_with("b") }
+ end
+
context "with a string" do
it "passes if it matches the end of the actual string" do
"this string".should end_with "is string"
View
5 spec/rspec/matchers/throw_symbol_spec.rb
@@ -2,6 +2,11 @@
module RSpec::Matchers::BuiltIn
describe ThrowSymbol do
+ it_behaves_like("an RSpec matcher", :valid_value => lambda { throw :foo },
+ :invalid_value => lambda { }) do
+ let(:matcher) { throw_symbol(:foo) }
+ end
+
describe "with no args" do
before(:each) { @matcher = throw_symbol }
View
28 spec/rspec/matchers/yield_spec.rb
@@ -35,6 +35,13 @@ def each_arg(*args, &block)
describe "yield_control matcher" do
include YieldHelpers
+ extend YieldHelpers
+
+ it_behaves_like "an RSpec matcher",
+ :valid_value => lambda { |b| _yield_with_no_args(&b) },
+ :invalid_value => lambda { |b| _dont_yield(&b) } do
+ let(:matcher) { yield_control }
+ end
it 'has a description' do
yield_control.description.should eq("yield control")
@@ -90,6 +97,13 @@ def each_arg(*args, &block)
describe "yield_with_no_args matcher" do
include YieldHelpers
+ extend YieldHelpers
+
+ it_behaves_like "an RSpec matcher",
+ :valid_value => lambda { |b| _yield_with_no_args(&b) },
+ :invalid_value => lambda { |b| _dont_yield(&b) } do
+ let(:matcher) { yield_with_no_args }
+ end
it 'has a description' do
yield_with_no_args.description.should eq("yield with no args")
@@ -154,6 +168,13 @@ def each_arg(*args, &block)
describe "yield_with_args matcher" do
include YieldHelpers
+ extend YieldHelpers
+
+ it_behaves_like "an RSpec matcher",
+ :valid_value => lambda { |b| _yield_with_args(1, &b) },
+ :invalid_value => lambda { |b| _dont_yield(&b) } do
+ let(:matcher) { yield_with_args }
+ end
it 'has a description' do
yield_with_args.description.should eq("yield with args")
@@ -283,6 +304,13 @@ def each_arg(*args, &block)
describe "yield_successive_args matcher" do
include YieldHelpers
+ extend YieldHelpers
+
+ it_behaves_like "an RSpec matcher",
+ :valid_value => lambda { |b| [1, 2].each(&b) },
+ :invalid_value => lambda { |b| _dont_yield(&b) } do
+ let(:matcher) { yield_successive_args(1, 2) }
+ end
it 'has a description' do
yield_successive_args(1, 3).description.should eq("yield successive args(1, 3)")
View
13 spec/support/shared_examples.rb
@@ -0,0 +1,13 @@
+shared_examples_for "an RSpec matcher" do |options|
+ let(:valid_value) { options.fetch(:valid_value) }
+ let(:invalid_value) { options.fetch(:invalid_value) }
+
+ it 'matches a valid value when using #== so it can be composed' do
+ expect(matcher).to eq(valid_value)
+ end
+
+ it 'does not match an invalid value when using #== so it can be composed' do
+ expect(matcher).not_to eq(invalid_value)
+ end
+end
+
Please sign in to comment.
Something went wrong with that request. Please try again.