Description
Subject of the issue
rspec/rspec-expectations#1073 seems to break subset hash matching for objects implementing #to_hash
and #include?
. Previously these objects were converted using #to_hash
on actual
. Due to not converting to a Hash
the check in comparing_hash_to_a_subset?
will always be false and subset check won't be performed anymore (unless the objects #include?
implements subset matching).
We had lots of breaking tests after the rspec-expectations
patch update due to having specs on e.g. ActionDispatch::Response::Header
like this:
expect(response.headers).to include 'Location' => 'http://test.host/...'
These expectations produced a nice diff when failing showing all send headers. We currently fixed it by explicitly calling #to_hash
on these objects.
It would be nice if such use case could still be supported.
Your environment
- Ruby version: ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
- rspec-expectations version: 3.8.2
Steps to reproduce
Run the following test case:
begin
require 'bundler/inline'
rescue LoadError => e
$stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true) do
source 'https://rubygems.org'
gem 'rspec-expectations', '3.8.2'
gem 'minitest'
end
require 'rspec/matchers'
require 'minitest/autorun'
class CollectionLikeObject
def to_hash
{'Header' => 'Value'}
end
def include?(key)
to_hash.include?(key)
end
end
class IncludeTest < Minitest::Test
def test_subset_match
matcher = RSpec::Matchers::BuiltIn::Include.new('Header' => 'Value')
actual = CollectionLikeObject.new
assert matcher.matches?(actual)
end
end
Running the test case with 3.8.1
passes.
Expected behavior
I'd expect the expectations to still pass after a patch level upgrade.
Actual behavior
All expectations failed while showing a nice diff showing no difference.