Skip to content

Commit

Permalink
Merge pull request #193 from rspec/hash_match_array_failure
Browse files Browse the repository at this point in the history
Provide a clear failure message when using `{}.should =~ {}`.
  • Loading branch information
myronmarston committed Dec 6, 2012
2 parents abefb76 + c7a91af commit cf52fe6
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/rspec/matchers.rb
Expand Up @@ -684,6 +684,6 @@ def match_array(array)
BuiltIn::MatchArray.new(array) BuiltIn::MatchArray.new(array)
end end


OperatorMatcher.register(Array, '=~', BuiltIn::MatchArray) OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
end end
end end
18 changes: 17 additions & 1 deletion lib/rspec/matchers/operator_matcher.rb
Expand Up @@ -31,7 +31,7 @@ def initialize(actual)


def self.use_custom_matcher_or_delegate(operator) def self.use_custom_matcher_or_delegate(operator)
define_method(operator) do |expected| define_method(operator) do |expected|
if matcher = OperatorMatcher.get(@actual.class, operator) if uses_generic_implementation_of?(operator) && matcher = OperatorMatcher.get(@actual.class, operator)
@actual.send(::RSpec::Matchers.last_should, matcher.new(expected)) @actual.send(::RSpec::Matchers.last_should, matcher.new(expected))
else else
eval_match(@actual, operator, expected) eval_match(@actual, operator, expected)
Expand Down Expand Up @@ -62,6 +62,22 @@ def description


private private


if Method.method_defined?(:owner) # 1.8.6 lacks Method#owner :-(
def uses_generic_implementation_of?(op)
@actual.method(op).owner == ::Kernel
end
else
def uses_generic_implementation_of?(op)
# This is a bit of a hack, but:
#
# {}.method(:=~).to_s # => "#<Method: Hash(Kernel)#=~>"
#
# In the absence of Method#owner, this is the best we
# can do to see if the method comes from Kernel.
@actual.method(op).to_s.include?('(Kernel)')
end
end

def eval_match(actual, operator, expected) def eval_match(actual, operator, expected)
::RSpec::Matchers.last_matcher = self ::RSpec::Matchers.last_matcher = self
@operator, @expected = operator, expected @operator, @expected = operator, expected
Expand Down
15 changes: 15 additions & 0 deletions spec/rspec/matchers/match_array_spec.rb
Expand Up @@ -113,6 +113,17 @@ def ==(other)
MESSAGE MESSAGE
end end


context "when the array defines a `=~` method" do
it 'delegates to that method rather than using the match_array matcher' do
array = []
def array.=~(other)
other == :foo
end

array.should =~ :foo
expect { array.should =~ :bar }.to fail_with(/expected: :bar/)
end
end
end end


describe "should_not =~ [:with, :multiple, :args]" do describe "should_not =~ [:with, :multiple, :args]" do
Expand All @@ -135,4 +146,8 @@ def ==(other)
it "fails with a string and the expected error message is given" do it "fails with a string and the expected error message is given" do
expect { "I like turtles".should match_array([1,2,3]) }.to fail_with(/expected an array/) expect { "I like turtles".should match_array([1,2,3]) }.to fail_with(/expected an array/)
end end

it 'fails with a clear message when given a hash using the `should =~` syntax' do
expect { {}.should =~ {} }.to fail_with(/expected an array/)
end
end end

0 comments on commit cf52fe6

Please sign in to comment.