Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

undefined method `visit' for #<RSpec::Core::ExampleGroup:.... #360

Closed
be9 opened this Issue · 65 comments
@be9
be9 commented

I'm having trouble with my Capybara integration specs and rspec-rails 2.6.0.rc4.

  9) My profile should show profile
     Failure/Error: login_as @user
     undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_4:0x748aab0>
     # ./spec/support/request_helpers.rb:8:in `login_as'
     # ./spec/integration/user/profile_spec.rb:6

It's simple visit '/' which explodes.

2.6.0.rc2 works great. What has been changed? Capybara version is 1.0.0.beta1

@dchelimsky
Owner

rc4 adds more support for Capybara 0.4 and 1.0. How/where are you requiring capybara?

@be9
be9 commented

I have require 'capybara/rspec' line in spec/support/additional_requires.rb

@dchelimsky
Owner

Try getting rid of that and tell me what happens. rspec-rails already does this, so it might be that doing it a second time is causing a problem due to module reloading, etc.

@be9
be9 commented

I've commented out the require line, but nothing changed. visit is still broken.

@dchelimsky
Owner

What's in your Gemfile?

@be9
be9 commented

Posted Gemfile here: https://gist.github.com/952141

@dchelimsky
Owner

I just ran this: https://gist.github.com/952630 and the spec with visit in it passed. Do you get the same result from that gist?

@be9
be9 commented

Works here too. I tried to make visit explode by copying in Gemfile and other stuff from my project but it still passes.

On the other side, I experimented with rspec-rails git and found out that this commit exactly: 59793dc breaks things for me (the specs pass with the preceding one when rspec-rails is pulled from git).

@be9
be9 commented

The test example works if I manually add include Capybara::DSL.

How come it doesn't get included?

@be9
be9 commented

So, I found it. The example that also breaks for your example app:

require "spec_helper"
describe "things" do
    it "works with visit" do
      go_things
      page.status_code.should eq(200)
    end
end

The cause of the bug is as follows. If we look at the :include_or_extend_modules array in rspec configuration, we see following:

   [[:extend, RSpec::Matchers::DSL, {}],
     [:include, RSpec::Rails::FixtureSupport, {}],
     [:include, RSpec::Rails::Mocks, {}],
     [:include, Capybara::Features, {:capybara_feature=>true}],
     [:include, Capybara::DSL, {:type=>:request}],
     [:include, Capybara::DSL, {:type=>:acceptance}],
     [:include, Capybara::RSpecMatchers, {:type=>:request}],
     [:include, Capybara::RSpecMatchers, {:type=>:acceptance}],
     [:include,
      RSpec::Rails::ControllerExampleGroup,
      {:type=>:controller,
       :example_group=>{:file_path=>/spec[\\\/]controllers/}}],
     [:include,
      RSpec::Rails::HelperExampleGroup,
      {:type=>:helper, :example_group=>{:file_path=>/spec[\\\/]helpers/}}],
     [:include,
      RSpec::Rails::MailerExampleGroup,
      {:type=>:mailer, :example_group=>{:file_path=>/spec[\\\/]mailers/}}],
     [:include,
      RSpec::Rails::ModelExampleGroup,
      {:type=>:model, :example_group=>{:file_path=>/spec[\\\/]models/}}],
     [:include,
      RSpec::Rails::RequestExampleGroup,
      {:type=>:request,
       :example_group=>{:file_path=>/spec[\\\/](requests|integration)/}}],
     [:include,
      RSpec::Rails::RoutingExampleGroup,
      {:type=>:routing, :example_group=>{:file_path=>/spec[\\\/]routing/}}],
     [:include,
      RSpec::Rails::ViewExampleGroup,
      {:type=>:view, :example_group=>{:file_path=>/spec[\\\/]views/}}],
     [:include, Devise::TestHelpers, {:type=>:controller}],
     [:include, RequestHelpers, {:type=>:request}],
     [:include, GlobalSpecHelpers, {}]]}>

(that's from my project). So Capybara::DSL gets included before RSpec::Rails::RequestExampleGroup. The former has :type => :request filter, but the type itself is set when the latter is included. So Capybara::DSL module is rejected by the filter and not included.

In your test example, with double describe block, module inclusion occurs twice. The second time type is already set, Capybara::DSL gets included, everything works.

The fix should be darn simple (haven't got more time right now, but I'll come up with it in the case you don't fix it first :)

@be9 be9 referenced this issue from a commit in be9/rspec-rails
@be9 be9 Require capybara after rspec/rails/example
Otherwise Capybara's includes are not set correctly.

Fixes #360
c19e295
@be9
be9 commented

Fix is available as pull request #362

@dchelimsky dchelimsky closed this issue from a commit
@be9 be9 Require capybara after rspec/rails/example
Otherwise Capybara's includes are not set correctly.

- Closes #360
- Closes #362
d0e790e
@dchelimsky dchelimsky closed this in d0e790e
@tommysqueak

I've got the same isssue (undefined method `visit' etc). I'm using capybara 1.0.0.beta1 I've got the rspec-rails and dependencies in my gemfile pointing to github. So I would have thought I'd have the latest, which includes the above commit? I have require 'rspec/rails' in my spec_helper.rb. It's in a new project I'm just getting started with. I'm also just getting started with rails, so I'm totally lost. Any help would be much appreciated.

@jackkinsella

I ran into the same problem today with rspec-rails 2.6.1 and capybara 1.0.0

#spec_helper.rb

require 'rubygems'
require 'spork'
require "email_spec"
ENV["RAILS_ENV"] ||= 'test'     
Spork.prefork do
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
end
Spork.each_run do
  Dir[Rails.root.join("site/app/**/*.rb")].each {|f| require f}     
  require "#{Rails.root}/spec/factories.rb"
end
@jackkinsella

Problem was due to the 'steak' gem. Once I removed it the Capybara methods worked once again.

@dchelimsky
Owner

@jackkinsella - glad to hear it, though a lot of people like to use steak so I'd like to understand why that doesn't work.

As an aside, I'd recommend the following changes to your spork config in spec_helper:

#spec_helper.rb

require 'rubygems'
require 'spork'
ENV["RAILS_ENV"] ||= 'test'

Spork.prefork do
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'email_spec' # shouldn't really need this if it's in the :test group in the Gemfile
end

Spork.each_run do
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
end

This assumes moving spec/factories.rb to spec/support. You don't need to require anything from app/** because Rails does that for you.

@jackkinsella

Thanks Dave; I hadn't thought of putting the factories into the support dir. I'm aware that I don't need to require anything from app/, but I have a gem in site/app/ which I'm actively developing.

I decided against using Steak for the same reason I've stopped using Cucumber: unwarranted additional abstraction. Rspec and Capybara do the same job with less lines of code and with fewer configuration headaches.

@dchelimsky
Owner

Ah - missed that it was site/app. Cheers.

@derekprior

I'm still seeing this with the latest rspec and rspec-rails. The visit method is undefined unless I nest my tests inside a second describe. As a result, I wrap my tests in a meaningless secondary describe.

I am using spork, so perhaps that has something to do with it?

require 'rubygems'
require 'spork'

Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'capybara/rspec'
  require 'rspec/rails'
  require 'database_cleaner'

  # use capybara-webkit
  Capybara.javascript_driver = :webkit

  # calls to DatabaseCleaner.clean will use truncation
  # otherwise, we will still use transactional fixtures
  DatabaseCleaner.strategy = :truncation

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    config.treat_symbols_as_metadata_keys_with_true_values = true
    config.mock_with :rspec
    config.fixture_path = "#{::Rails.root}/spec/fixtures"
    config.use_transactional_fixtures = true
    config.include ModelMacros
    config.include ActionView::TestCase::Behavior, :example_group => {:file_path => %r{spec/presenters}}
    # config.include FactoryGirl::Syntax::Methods

    config.before(:suite) do
      # Create the admin user
      Factory(:user, :login => ENV['REMOTE_USER'], :roles_mask => 1)
    end
  end
end

Spork.each_run do
  # verifies we start with a clean database each run
  DatabaseCleaner.clean

  # require factories
  require 'factory_girl_rails'
  RSpec.configure do |config|
    config.include FactoryGirl::Syntax::Methods
  end
end

# This allows us to use transactional fixtures when
# using selenium/capybara-webkit by forcing them to use
# the same thread as capybara.
ActiveRecord::ConnectionAdapters::ConnectionPool.class_eval do
  def current_connection_id
    Thread.main.object_id
  end
end
@aia

Getting the same error with rspec-rails (2.8.1) and capybara (1.1.2).
Have to manually include Capybara::DSL.

@dchelimsky
Owner

@derekprior, @ala I can't repro this on my system w/ Mac OS and ruby 1.9.3. What OS and ruby versions are you running?

@derekprior

I'm running OS X 10.6.8, with Ruby 1.9.2-p290. I'll take a shot at distilling a simplified reproduction.

@aia

Running on OS X too:

rvm -v
rvm 1.10.3 by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.beginrescueend.com/]

ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0]

@derekprior

Okay, @dchelimsky, I think I boiled it down to a base case (at least in my case). Please see this repository:
https://github.com/derekprior/rspec_rails_bug

The reproduction succeeds (visit is undefined) if I require capyabara/rspec before rspec/rails in spec_helper.rb. Interestingly, it seems completely unnecessary to require capyabara/rspec at all as removing that line completely makes all tests pass. Requiring rspec/rails first also causes all tests to pass.

The repository I linked to will produce a failing spec on 1.9.2-p290 and 1.9.3-p0. I suspect the same is true of 1.8.7, but I didn't have time to correct the hash syntax and re-run the tests there.

Seems like "leave it to rspec-rails to require capyabara" is the way to go. I think that line was in my spec_helper from days prior to whatever version of rspec-rails added the automatic require.

@derekprior

Actually, it appears that test case isn't true to my actual project issue. In my actual project, neither removing or re-ordering the requires fixes anything. Calls to visit still must be at least 2 describes deep. Odd.

I'll keep looking...

@aia
#
#  *Working*
# spec/controller/pages_controller_spec.rb
#
require 'spec_helper'

describe PagesController do
  render_views

  describe "GET 'home'" do
    it "should be successful" do
      visit '/'
      response.should be_successful
    end
  end
end
#
# *Not Working*
# spec/requests/user_registration_spec.rb
#
require 'spec_helper'

describe "user registration" do  
  it "should serve the registration page" do
    visit '/signup'
    page.should have_content("Sign Up")
  end
end
@dchelimsky
Owner

@ala - what's not working? You're getting undefined method on visit? Or something else?

@aia

@dchelimsky yes, getting the undefined visit method.

@dchelimsky
Owner

@ala is your repo public?

@aia

@dchelimsky unfortunately no. Let me see if I can cut out that example. Should be a pretty basic Rails 3.2 app.

@duckpond

I'm seeing this identical issue. We had

  config.include RSpec::Rails::RequestExampleGroup, :example_group => { :file_path => /spec\/externals/ }

in our spec_helper but it was still getting undefined method 'visit'.

@dnd

Just another mention that I'm having the same problem described by aia. If I nest the visit call two describes deep then it works fine. This is on rspec* 2.9.0

@dchelimsky
Owner

Folks - I need a repro. Can anybody who is experiencing this problem post a repo to github that I can clone, bundle, run, and see the issue?

@derekprior

I will try to cleans my app of anything proprietary and post the repro

@derekprior

Alright, here's a repo:
https://github.com/derekprior/rspec-rails-capybara-bug

In my case it seems that the gem 'capybara-screenshot' is causing the problem. If I remove this gem from the gemfile, both specs pass. I've tried keeping it in with various gem orderings, but I have not had any success. I haven't yet dug into this gem to see what's going on.

Curious if other folks having problems also have this gem?

@dnd

I can't try removing that gem from mine at the moment, but I am also using 'capybara-screenshot', version 0.1.10 to be specific.

@derekprior

Here's what capybara-screenshot is doing on load:
https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot.rb

I don't know enough about the internals to say what the problem is off hand, but perhaps David or someone else does?

@dchelimsky
Owner

It's definitely a load order integration bug. I don't understand it yet, but you can work around it by doing the following:

# in Gemfile
  gem 'capybara-screenshot', :require => false

# in spec/spec_helper.rb
  require 'rspec/rails'
  require 'capybara-screenshot'
@dchelimsky
Owner

Also - @derekprior thanks for posting the app - that helped me see the bug, figure out the workaround, and will eventually lead to a fix.

@5minpause

Unfortunately this workaround doesn't do it for me. I still get

NoMethodError:
   undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_1::Nested_1:0x007fbfeb535298>

The repo is public under: https://github.com/ikusei/Goldencobra_Newsletter
You need to look at the branch '28817499-subscribe'

edit: If i put include Capybara::DSL inside my describe block it works.

@bigtunacan

I see this is marked as closed, but I'm having this same issue

@5minpause

Did you see my edit? After doing that it worked for me.

@bigtunacan

@jazzgumpy , Thanks that works for me as well using include Capybara::DSL within my outer describe

@henrik

@dchelimsky I started on a new app and ran into this, so this is a very small (if not minimal) failure case with RSpec 2.11: https://dl.dropbox.com/u/546793/joblog.zip

Note that there is a workaround (config.include Capybara::DSL) in spec/spec_helper.rb:19, so comment that out to (hopefully) reproduce.

(And I will of course make sure to change the secret_token.)

@henrik

@bigtunacan @jazzgumpy A slightly nicer workaround is to put

config.include Capybara::DSL

in spec_helper.rb, inside the config block.

@dchelimsky
Owner

@henrik the directory is requests (plural), not request. Try that and it works as expected.

@henrik

@dchelimsky Thanks, that did work. Sorry for bothering you with such a silly mistake. Maybe @jazzgumpy and @bigtunacan made similar mistakes.

Would be nice if it was harder to make a mistake, or easier to recover from it, but I can't think of how, other than maybe emphasizing it in the docs. Pull request for that: #585

@dchelimsky
Owner

I merged your pull request, so that should help. Thx. Also, the integration test generator puts it in the right place.

@wojtha

I've run in this issue after update to capybara 2.0. First I implemented the henrik's workaround by mixing Capybara::DSL methods to Rspec but now I've found this in the Capybara 2.0 update notes:

To upgrade to capybara 2.0, you'll need to do a few things:

Move any tests that use capybara from spec/requests to spec/features. Capybara tests use the visit method and usually assert against page. Alternatively, you can keep using capybara in request specs, but you'll need to manually mix in the methods.

See http://alindeman.github.com/2012/11/11/rspec-rails-and-capybara-2.0-what-you-need-to-know.html

I have my tests in the old path spec/requests of course ...

Might be it could help someone.

@reejosamuel

for others facing the issue, renaming request to requests is no longer the problem, all requests need to be moved to features folder

@matt-hwy1

2wojtha and @reejosamuel, thank you. I renamed my requests dir to features and that fixed it!

@pcerioli

thank you @wojtha.
That fixed the issue for me.

@george

renaming requests to features worked here, too. Thx.

@eschaefer

ditto for me @george

@alindeman
Collaborator

For reference, it's documented in Capybara.md and this blog post

@Chrisgo-75

renamed requests to features. Problem fixed. Thank you.

@IamNaN

I'm using rails 4.0.0.beta1. Renamed the requests folder to features, but still needed to add config.include Capybara::DSL to spec_helper.rb.

@blazeeboy

i got the same problem and fixed with 2 way :
1- renaming the "requests" directory to "features"
2- the work around of adding Capybara DSL to my rspec helper mentioned above

thanks guys

@dmxforever

renaming "requests" to "features" fix it. rails 4

@lucasdavila

:+1: renaming "requests" to "features" fixed it, on Rails 3.

@longli

1、add "gem "rspec-rails", "~> 2.0" and gem 'capybara', '~>1.1.2'" in Gemfile
2、bundle install
3、add “config.include Capybara::DSL” in spec_helper.rb
OK! Good luck for you!

@flyfy1

Hmm I think it might be helpful to add the poing number 3 into the README.md file of capybara so that when people use they don't need to do search for the problem again.

@nathanhamilton

Renaming the spec/requests folder to spec/features got things rolling for me too. Thanks for the help.

@StevenClontz

Renaming the spec/requests folder to spec/features got things rolling for me too. Thanks for the help.

+1

@alexrothenberg alexrothenberg referenced this issue from a commit in alexrothenberg/rspec-rails
@henrik henrik Clarify when webrat/capybara autoloading applies.
Since I got it wrong: rspec#360
3622324
@lukexuanliu

I followed all the different work-around (or I think I did) in this post and still could not get it working. I still see the NoMethodError. My repo is a really basic practice website. Please help at
https://github.com/lukexuanliu/CornellBlog/tree/static_pages
Thanks everyone!

@JonRowe
Owner

You need to add a require 'rails_helper' line beneath require 'spec_helper', in future please use the RSpec mailing list for questions like this, not issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.