rspec-expectations icon indicating copy to clipboard operation
rspec-expectations copied to clipboard

`have_attributes` attribute detail is missing when passed to another matcher

Open myronmarston opened this issue 10 years ago • 4 comments

In #668, the have_attributes matcher was improved so that the actual attribute values are used in the diff. This is particularly important when the inspect output of the object does not include the attribute values.

However, the issue from #667 remains when you pass have_attributes (or an alias) to another matcher. Consider this spec:

RSpec.describe "have_attributes" do
  example "using `have_attributes` directly" do
    expect(1).to have_attributes(:__id__ => 4)
  end

  example "passing `an_object_having_attributes` to another matcher" do
    expect([1, 2]).to match [
      an_object_having_attributes(:__id__ => 4),
      an_object_having_attributes(:__id__ => 5)
    ]
  end
end

Running that produces two failures:

  1) have_attributes using `have_attributes` directly
     Failure/Error: expect(1).to have_attributes(:__id__ => 4)
       expected 1 to have attributes {:__id__ => 4} but had attributes {:__id__ => 3}
       Diff:
       @@ -1,2 +1,2 @@
       -:__id__ => 4,
       +:__id__ => 3,

  2) have_attributes passing `an_object_having_attributes` to another matcher
     Failure/Error: expect([1, 2]).to match [
       expected [1, 2] to match [(an object having attributes {:__id__ => 4}), (an object having attributes {:__id__ => 5})]

The failure from the first spec clearly shows that the value of __id__ was that did not match. The failure from the 2nd spec doesn't show that at all, which is annoying because it's hard to tell why the match failed without that information.

myronmarston avatar Mar 30 '15 23:03 myronmarston

@myronmarston I'll start to think off a general solution for have_attributes matcher

mrageh avatar Oct 25 '15 16:10 mrageh

Any ideas what output we'd like to have when passing to another matcher, i.e. 2nd example? Would something like this be good (...but had attributes {:id => 3}):

2) have_attributes passing `an_object_having_attributes` to another matcher
     Failure/Error: expect([1]).to match [
       expected [1] to match [(an object having attributes {:__id__ => 4} but had attributes {:__id__ => 3})]

nellirx avatar Apr 24 '22 23:04 nellirx

@nellirx That would certainly be an improvement. Would you like to hack on it?

pirj avatar Apr 25 '22 05:04 pirj

Would you like to hack on it?

yes please, thanks

nellirx avatar Apr 25 '22 10:04 nellirx