Rails: RSpec - undefined method `cookie_jar' for nil:NilClass

authentication, capybara, rspec, ruby, ruby-on-rails

Solution

RSpec is very particular about the directory that you place your tests. If you put the test in the wrong directory, it won't automagically mix-in the various test helpers that setup different types of tests. It seems your setup is using `spec/features` which is not an approved default directory (`spec/requests`, `spec/integration`, or `spec/api`).

Based on the tutorial page, I'm not sure how they have the `spec_helper.rb` file setup. Though the examples so they are using `spec/requests` to hold the tests.

You can force RSpec to recognize another directory for request specs by using on of the following:

Manually add the proper module to the test file:

# spec/features/pages/index_spec.rb
require 'spec_helper'

describe "Visiting the index page" do

  include RSpec::Rails::RequestExampleGroup

  # Rest of your test code
  context "when the a user has logged in and attempts to visit the page" do
    let(:user) { FactoryGirl.create :user }

    before do 
      log_in user
    end

    specify { response.should redirect_to loggedin_path }
  end

end

Include this in your `spec/spec_helper.rb` file:

RSpec::configure do |c|
  c.include RSpec::Rails::RequestExampleGroup, type: :request, example_group: {
    file_path: c.escaped_path(%w[spec (features)])
  }
end

Since this is a tutorial I'd recommend following the standard of including `require 'spec_helper'` at the top of the spec file and that your actual `spec/spec_helper.rb` file has `require 'rspec/rails'`

A minor note, you don't need to put a `specify` inside of an `it` block. They are aliases of each other, so just use one.

context "when the a user has logged in and attempts to visit the page" do
  let(:user) { FactoryGirl.create :user }

  before do 
    log_in user
  end

  # All of the following are the same

  it "redirects the user to next page" do
    response.should redirect_to loggedin_path
  end

  it { response.should redirect_to loggedin_path }

  specify "redirects the user to next page" do
    response.should redirect_to loggedin_path
  end

  specify { response.should redirect_to loggedin_path }
end

Note, according to the documentation for capybara, you should be able to put your capybara tests into `spec/features`. To make this work, ensure you are loading `require 'capybara/rspec'` in your `spec_helper` or test spec file directly.

However, looking at the source, I didn't see where they are automatically including that directory. You can also try adding the tag `type: :feature` to the outer `describe` block in your test file. Though the more likely solution is to use `spec/requests`.

Problem

Rails newbie. Trying to follow Michael Hartl's tutorial. Stuck trying to add a helper method to simulate log in an RSpec test: ``` describe "when the a user has logged in and attempts to visit the page" do let(:user) { FactoryGirl.create :user } before do log_in user end it "should redirect the user to next page" do specify { response.should redirect_to loggedin_path } end end ``` In my spec/support/utilities.rb: ``` def log_in user visit root_path fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Log in" cookies[:remember_token] = user.remember_token end ``` Error: ``` Failure/Error: log_in user NoMethodError: undefined method `cookie_jar' for nil:NilClass ``` What gives? Edit, full stack trace: ``` Index page when the a user has logged in and attempts to visit the page should redirect the user to next page Failure/Error: log_in user NoMethodError: undefined method `cookie_jar' for nil:NilClass # ./spec/support/utilities.rb:8:in `log_in' # ./spec/features/pages/index_spec.rb:20:in `block (3 levels) in <top (required)>' ```

Original source