Rails Rspec error - undefined method `visit'

10,183

Solution 1

The problem is here:

./spec/requests/user_pages_spec.rb

You put the Capybara integration tests in requests folder. That's why the method visit won't work.

To fix, just move all the tests from spec/requests to spec/features.

Solution 2

This happens because you are trying to use the visit method from Capybara::DSL. If you check the documentation:

 Capybara is no longer supported in
 request specs as of Capybara 2.0.0. The recommended way to use Capybara is
 with feature specs.

To solve this problem you should move your tests to spec/features folder or include Capybara::DSL for the request specs:

#spec_helper.rb
RSpec.configure do |config|
  #...
  config.include Capybara::DSL, :type => :request
Share:
10,183
BB500
Author by

BB500

User Interface Developer making the jump into back-end programming

Updated on September 20, 2022

Comments

  • BB500
    BB500 over 1 year

    So I'm new to TDD & I'm throwing some Rspec errors here on my tests...Basically after running bundle exec rspec spec, I get an undefined method 'visit' error on some of my specs. Any help on how to make these tests pass would be much appreciated: Thanks.

    Failures:
    
    1) User pages profile page 
     Failure/Error: before { visit user_path(user) }
     NoMethodError:
       undefined method `visit' for # <RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x007ffda8049540>
     # ./spec/requests/user_pages_spec.rb:9:in `block (3 levels) in <top (required)>'
    
    2) User pages profile page 
     Failure/Error: before { visit user_path(user) }
     NoMethodError:
       undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x007ffda4f3ac38>
     # ./spec/requests/user_pages_spec.rb:9:in `block (3 levels) in <top (required)>'
    
    3) User pages signup page 
     Failure/Error: before { visit signup_path }
     NoMethodError:
       undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_2:0x007ffda8262e58>
     # ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
    
    4) User pages signup page 
     Failure/Error: before { visit signup_path }
     NoMethodError:
       undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_2:0x007ffda82663c8>
     # ./spec/requests/user_pages_spec.rb:16:in `block (3 levels) in <top (required)>'
    
    Finished in 9.08 seconds
    24 examples, 4 failures
    
    Failed examples:
    
    rspec ./spec/requests/user_pages_spec.rb:11 # User pages profile page 
    rspec ./spec/requests/user_pages_spec.rb:12 # User pages profile page 
    rspec ./spec/requests/user_pages_spec.rb:18 # User pages signup page 
    rspec ./spec/requests/user_pages_spec.rb:19 # User pages signup page 
    

    My spec/requests/user_pages_spec.rb

    require 'spec_helper'
    
    describe "User pages" do
    
      subject { page }
    
      describe "profile page" do
        let(:user) { FactoryGirl.create(:user) } # Code to make a user variable
        before { visit user_path(user) }
    
        it { should have_selector('h1',    text: user.name) }
        it { should have_selector('title', text: user.name) }
      end
    
      describe "signup page" do
        before { visit signup_path }
    
        it { should have_selector('h1',    text: 'Sign up') }
        it { should have_selector('title', text: 'Sign up') }
      end
    end
    

    And my spec/models/user_spec.rb

    require 'spec_helper'
    
    describe User do
    
    before do
      @user = User.new(name: "Example User", email: "[email protected]",
                      password: "foobar", password_confirmation: "foobar")
    end
    
    subject { @user }
    
    it { should respond_to(:name) }
    it { should respond_to(:email) }
    it { should respond_to(:password_digest) }
    it { should respond_to(:password) }
    it { should respond_to(:password_confirmation) }
    it { should respond_to(:authenticate) }
    
    it { should be_valid }
    
    describe "when name is not present" do
      before { @user.name = " " }
      it { should_not be_valid }
    end
    
    describe "when email is not present" do
      before { @user.email = " " }
      it { should_not be_valid }
    end
    
    describe "when name is too long" do
      before { @user.name = "a" * 51 }
      it { should_not be_valid }
    end
    
    describe "when email format is invalid" do
      it "should be invalid" do
        addresses = %w[user@foo,com user_at_foo.org example.user@foo.
                       foo@bar_baz.com foo@bar+baz.com]
        addresses.each do |invalid_address|
          @user.email = invalid_address
          @user.should_not be_valid
        end      
      end
    end
    
    describe "when email format is valid" do
      it "should be valid" do
        addresses = %w[[email protected] [email protected] [email protected] [email protected]]
        addresses.each do |valid_address|
          @user.email = valid_address
          @user.should be_valid
        end      
      end
    end
    
    describe "when email address is already taken" do
      before do
        user_with_same_email = @user.dup
        user_with_same_email.email = @user.email.upcase
        user_with_same_email.save
      end
      it { should_not be_valid }
    end
    
    describe "when password is not present" do
      before { @user.password = @user.password_confirmation = " " }
      it { should_not be_valid }
    end
    
    describe "with a password that's too short" do
      before { @user.password = @user.password_confirmation = "a" * 5 }
      it { should be_invalid }
    end
    
    describe "return value of authenticate method" do
      before { @user.save }
      let(:found_user) { User.find_by_email(@user.email) }
    
      describe "with valid password" do
        it { should == found_user.authenticate(@user.password) }
      end
    
      describe "with invalid password" do
        let(:user_for_invalid_password) { found_user.authenticate("invalid") }
    
        it { should_not == user_for_invalid_password }
        specify { user_for_invalid_password.should be_false }
      end
    end 
    
    describe "when password doesn't match confirmation" do
      before { @user.password_confirmation = "mismatch" }
      it { should_not be_valid }
    end
    
    describe "when password confirmation is nil" do
      before { @user.password_confirmation = nil }
      it { should_not be_valid }
    end
    
    end
    

    And lastly my views/users/new.html.erb

    <% provide(:title, 'Sign up') %>
    <h1>Sign up</h1>
    <p>Find me in app/views/users/new.html.erb</p>
    

    and views/users/show.html.erb

    <% provide(:title, @user.name) %>
    <h1><%= @user.name %></h1>
    

    & I've added my UsersController

    class UsersController < ApplicationController
      def new
      end
    
      def show
       @user = User.find(params[:id])
      end
    end
    

    Also getting this new error now after fixing as per Billy's solution

    Failures:
    
    1) User pages signup page 
     Failure/Error: it { should have_selector('title', text: 'Sign up') }
     Capybara::ExpectationNotMet:
       expected to find css "title" with text "Sign up" but there were no matches. Also found "", which matched the selector but not all filters.
     # ./spec/features/user_pages_spec.rb:19:in `block (3 levels) in <top (required)>'
    
    2) User pages profile page 
     Failure/Error: it { should have_selector('title', text: user.name) }
     Capybara::ExpectationNotMet:
       expected to find css "title" with text "Michael Hartl" but there were no matches. Also found "", which matched the selector but not all filters.
     # ./spec/features/user_pages_spec.rb:12:in `block (3 levels) in <top (required)>'
    
    Finished in 9.41 seconds
    24 examples, 2 failures
    
    Failed examples:
    
    rspec ./spec/features/user_pages_spec.rb:19 # User pages signup page 
    rspec ./spec/features/user_pages_spec.rb:12 # User pages profile page 
    
  • Billy Chan
    Billy Chan about 11 years
    @BB500, you need to create that folder manually. You can even create sub folders under it such as spec/features/models.
  • Billy Chan
    Billy Chan about 11 years
    @BB500, please note the /features folder is only intended for integration tests which will use Capybara. For other functional tests such as model, controller, helpers etc, you don't need move them, and they won't need Capybara DSL such as visit.
  • BB500
    BB500 about 11 years
    Thanks man! - I moved that test file to a new features folder & those tests passed. (of course now i've got a couple new ones...maybe you can spot whats going on here as well??) I've edited the post.
  • BB500
    BB500 about 11 years
    thanks man - appreciate the help. (apparently i don't have enough reputation to "up" an answer
  • Billy Chan
    Billy Chan about 11 years
    @BB500, nice you fixed. And then welcome to TDD world. The errors you showed next are your best friends in TDD, along with your fixing them, you build the feature. If no title, supply the title, then, if anything need, supply it until test passed!
  • Admin
    Admin over 10 years
    Included Capybara in the Rspec help file instead of adding a new folder. Worked! +1