radical_edo
radical_edo

Reputation: 994

undefined method 'has_selector?' for rspec decorators

I have the following rspec test:

# spec/decorators/user_decorator_spec.rb    
require File.expand_path 'spec/spec_helper'

describe UserDecorator do
  let(:user) { UserDecorator.new build(:user, level: build(:level)) }
  subject { user }

  its(:avatar) { should have_selector 'h6' }
end

and I get error:

Failure/Error: its(:avatar) { should have_selector 'h6' }
     NoMethodError:
       undefined method `has_selector?' for #<ActiveSupport::SafeBuffer:0x007fecbb2de650>
     # ./spec/decorators/user_decorator_spec.rb:7:in `block (2 levels) in <top (required)>'

I have tried the popular suggestion with:

before { ApplicationController.new.set_current_view_context }

but then it says undefined method set_current_view_context. I'm using rspec 2.14.1 and capybara 2.0.1. Also, the strangest thing - when I wrote this test in some helper spec it passed, no problems...

Help...

Upvotes: 3

Views: 1713

Answers (3)

leandroico
leandroico

Reputation: 1227

I didn't feel very satisfied about using the type: :view solution proposed in this thread, despite it's a very valid one. The thing is that my spec file for a file inside lib/ directory shouldn't be actually considered as a view spec.

So I did some further research over the internet and found out one that seems a better approach to me.

So considering the original example in this thread. You should just add the following line inside your describe block:

include Webrat::Matchers

So the final example would look like:

# spec/decorators/user_decorator_spec.rb    
require File.expand_path 'spec/spec_helper'

describe UserDecorator do
  include Webrat::Matchers

  let(:user) { UserDecorator.new build(:user, level: build(:level)) }
  subject { user }

  its(:avatar) { should have_selector 'h6' }
end

Upvotes: 2

Tim Moore
Tim Moore

Reputation: 9482

The simplest fix is probably to add type: 'helper' or `type: 'view' to your describe block:

describe UserDecorator, type: 'helper' do
  let(:user) { UserDecorator.new build(:user, level: build(:level)) }
  subject { user }

  its(:avatar) { should have_selector 'h6' }
end

Doing so will mix ActionView::TestCase::Behavior and Capybara::RSpecMatchers in to your test.

Specs in your specs/helpers directory automatically get the 'helper' type, and specs in specs/views automatically get the 'view' type.

Since specs/decorators is a custom directory that isn't understood by rspec-rails, you need to configure the type manually.

See the RSpec Rails README for more information on the types of tests it supports.

Upvotes: 3

Billy Chan
Billy Chan

Reputation: 24815

has_selector or its alias have_selector is the method of Capybara, not Rspec.

You are using plain Rspec here, so these methods are not possible.

You can use a simple REGEX to check that:

its(:avatar) { should match(/h6.*img/ }

Upvotes: 1

Related Questions