undefined method 'has_selector?' for rspec

2019-07-04 17:20发布

问题:

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...

回答1:

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


回答2:

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.



回答3:

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/ }