2

I'm having trouble with equality matchers in RSpec and Draper decorated objects.

Specs to show what's going on:

context 'how to use the right equality matcher' do
  let(:page) { build(:page) }
  let(:decorated_page) { page.decorate }

  it "should pass, but doesn't" do
    expect(decorated_page).to_not eq page
  end

  it 'proves the classes are different' do
    expect(decorated_page).to be_a PageDecorator
    expect(page).to be_a Page
    expect(decorated_page.class).to_not eq page.class
  end

  it 'has a work around' do
    expect(decorated_page).to be_decorated_with PageDecorator
    expect(page).to_not be_decorated_with PageDecorator
  end
end

I know RSpec has a few different equality checkers, and that eq is the "weakest" but I would have thought not having the same class would be a deal breaker.

As you can see, I have a work around for this case thanks to Draper's matchers. But I feel like I must be missing something for that test to fail.

Question:

What equality matcher should I use to get the should pass, but doesn't test to pass?

Lucy Bain
  • 2,496
  • 7
  • 30
  • 45
  • The `eq` matcher just uses the `==` operator on the objects, so this isn't really an RSpec issue but a Draper issue. – David Grayson Dec 30 '14 at 05:46
  • what if you create page instead of build? – Rustam Gasanov Dec 30 '14 at 05:56
  • @DavidGrayson I agree. I hoped there was another equality matcher that would work for this case, but I think not. That's probably why Draper provides the work around matchers. – Lucy Bain Dec 30 '14 at 05:58
  • @RustamA.Gasanov Nope, same problem. I think David has the right idea - this just isn't how Draper is expected to work. – Lucy Bain Dec 30 '14 at 05:59

1 Answers1

1

I think that you're encountering two misunderstandings.

  1. You're asking about testing whether the page is decorated or not. You shouldn't test for this. Instead, you should test for the outcome of the decoration, i.e. the behavior. For example if the decorator is supposed to add a new method "foo" then test that the "foo" method works the way you want.

  2. The Draper decorator makes model.decorate == model. This intentionally makes the decoration "invisible" to testing code. For example, expect(decorated_page).to eq page will succeed, because RSpec is using == for the comparison, then Draper is intercepting ==. This is why your spec that says "should pass, but doesn't" is behaving the way it is.

If you really do want to test that decoration happened to the page, try this:

expect(decorated_page.object).to eq page

If you really do want to test that the decorated page is different than the page, try this:

expect(decorated_page.object_id).to_not eq page.object_id
joelparkerhenderson
  • 34,808
  • 19
  • 98
  • 119
  • 1. the code for that test is `expect(decorated_page).to_not eq page` - as in, I think `decorated_page` should not equal `page`. That test fails - as in, RSpec things `decorated_page` and `page` are equal. 2. I have separate decorator tests to make sure the methods on the decorator work as expected. This test is to make sure the decoration is applied in the first place. – Lucy Bain Dec 30 '14 at 06:11
  • I like your idea for `expect(decorated_page.object).to eq page` - it tests that decoration happened, and that it happened on the right object. Thanks! – Lucy Bain Dec 30 '14 at 06:12
  • I added more info to explain better - see if that helps and let me know if you want more detail – joelparkerhenderson Dec 30 '14 at 06:38