3
votes

I've written the following rspec feature test spec:

require "rails_helper"

RSpec.describe "Team management", type: :feature do
  user_sign_in

  describe "User creates a new team" do
    ...    
    expect(page).to have_link("#{team_name}")
  end
end

The user_sign_in method is defined in my rails_helper.rb:

ENV['RAILS_ENV'] ||= 'test'
require 'spec_helper'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'capybara/rails'

...

module UserSignInHelpers
  def user_sign_in
    before(:each) do
      @request.env['devise.mapping'] = Devise.mappings[:user]

      @current_user = FactoryGirl.create(:user)
      @current_user.confirm

      sign_in :user, @current_user
    end
  end
end

RSpec.configure do |config|
  ...
  # The different available types are documented in the features, such as in
  # https://relishapp.com/rspec/rspec-rails/docs
  config.infer_spec_type_from_file_location!

  config.extend UserSignInHelpers,    type: :controller
  config.extend UserSignInHelpers,    type: :feature
  config.include Devise::TestHelpers, type: :controller
  config.include Devise::TestHelpers, type: :feature
end

The user_sign_in method works from all of my controller specs but when I run my feature spec it fails with:

Team management
  User creates a new team
    example at ./spec/features/user_creates_a_new_team_spec.rb:19 (FAILED - 1)

Failures:

  1) Team management User creates a new team
     Failure/Error: Unable to find matching line from backtrace
     NoMethodError:
       undefined method `env' for nil:NilClass
     # /Users/xxxx/.rvm/gems/ruby-2.2.1/gems/devise-3.5.1/lib/devise/test_helpers.rb:24:in `setup_controller_for_warden'

I don't understand why this works in controller tests and not feature tests. Is there something I can do make this work in feature tests?

1

1 Answers

4
votes

There is a basic problem with what you are trying to do. (Devise work on top of Warden)Warden is a Rack middleware, but RSpec controller specs don't even include Rack, as these types of specs are not meant to run your full application stack, but only your controller code.

Ref

Test with Capybara

I have a simple support helper, that allows me to login and logout users:

module Auth
  def create_user!
    @user = User.create(email: '[email protected]', password: '11111111')
  end

  def sign_in_user!
    setup_devise_mapping!
    sign_in @user
  end

  def sign_out_user!
    setup_devise_mapping!
    sign_out @user
  end

  def setup_devise_mapping!
    @request.env["devise.mapping"] = Devise.mappings[:user]
  end

  def login_with_warden!
    login_as(@user, scope: :user)
  end

  def logout_with_warden!
    logout(:user)
  end

  def login_and_logout_with_devise
    sign_in_user!
    yield
    sign_out_user!
  end

  def login_and_logout_with_warden
    Warden.test_mode!
    login_with_warden!
    yield
    logout_with_warden!
    Warden.test_reset!
  end
end

in a feature:

RSpec.describe "Team management", type: :feature do
  describe "User creates a new team" do
     login_and_logout_with_warden do
       # tests goes here
     end
  end
end

in a controller:

RSpec.describe "Team management", type: :controller do
  describe "User creates a new team" do
    login_and_logout_with_devise do
      # tests goes here
    end
  end
end