Rumpleteaser
Rumpleteaser

Reputation: 4234

RSpec Devise sign_in not setting current_user in controller

I have followed the instructions found in: Devise wiki on setting up controller tests with RSpec but my tests are failing.

Instead of rendering the page it appears to be redirecting to http://test.host

Here are a few things from the response:

@current_user=nil
@_response_body=["<html><body>You are being <a href=\"http://test.host/\">redirected</a>.</body></html>"]

My test controller spec looks like:

require 'rails_helper' require 'devise'

RSpec.describe Services::MyController, :type => :controller do   
  include Devise::TestHelpers   
  include Warden::Test::Helpers   

  describe "administrator" do
    before :each do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      #administrator wraps user and adds role
      @admin = FactoryGirl.create(:administrator)
      @admin.confirm!
      sign_in @admin
    end
    describe "GET index" do
      it "returns http success" do
        #puts current_user.to_yaml
        get :index
        expect(response).to be_success
      end
    end   
  end 
end

It looks like its automatically redirecting to test.host (no idea where that comes from) because there is no current user defined?

In my application controller I have code setup to log the user out if they are logged in somewhere elsewhere. This appears to be where the user is being automatically redirected. From dumping the current_user here I can see that 'current_sign_in_ip' is nil as are all the other sign in attributes are not set.

ApplicationController

def check_request_ip
    puts current_user.to_yaml
    puts request.remote_ip
    unless current_user.nil? || request.remote_ip == current_user.current_sign_in_ip
      Rails.logger.warn "User already logged in from #{current_user.current_sign_in_ip} and trying to log in from #{request.remote_ip}."
      sign_out_and_redirect(current_user)
    end
  end

rails_helper.rb

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

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

ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

RSpec.configure do |config|

  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  config.use_transactional_fixtures = true

  config.infer_spec_type_from_file_location!
end

spec_helper.rb

require 'factory_girl'
require 'devise'
RSpec.configure do |config|
  begin
    config.include Warden::Test::Helpers
    config.include Devise::TestHelpers, :type => :controller
    config.include FactoryGirl::Syntax::Methods

    config.filter_run :focus
    config.run_all_when_everything_filtered = true

    if config.files_to_run.one?
      config.default_formatter = 'doc'
    end
    config.profile_examples = 10

    config.order = :random

    Kernel.srand config.seed

    config.expect_with :rspec do |expectations|
      expectations.syntax = [:expect, :should]
    end

    config.mock_with :rspec do |mocks|
      mocks.syntax = :expect
      mocks.verify_partial_doubles = true
    end
  end
end

test.rb

Go2Asset::Application.configure do

  config.stretches = Rails.env.test? ? 1 : 10
  config.cache_classes = true

  config.eager_load = false

  config.serve_static_assets = true
  config.static_cache_control = "public, max-age=3600"

  config.consider_all_requests_local = true
  config.action_controller.perform_caching = false

  config.action_dispatch.show_exceptions = false

  config.action_controller.allow_forgery_protection = false

  config.action_mailer.delivery_method = :test
  config.action_mailer.default_url_options = { :host => 'localhost:3000' }

  config.active_support.deprecation = :stderr
end

Upvotes: 3

Views: 3241

Answers (1)

Hani Alsioufi
Hani Alsioufi

Reputation: 167

Because you don't need to describe two describes as they are independent of each other (they are two different scenarios) that's why current_user is nil in the second describe

try to define a method used to create a user and sign him in, you can do so by creating a method in support/devise.rb as follows:

module ControllerMacros
  def login_user
    before(:each) do
      @request.env["devise.mapping"] = Devise.mappings[:user]
      user = FactoryGirl.create(:user) # in factories.rb you should create a factory for user
      user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the "confirmable" module
      sign_in user
    end
  end
end

RSpec.configure do |config|
  config.include Devise::TestHelpers, :type => :controller
  config.extend ControllerMacros, :type => :controller
end

Then delete the first describe, in the second describe just write before get :index

login_user

Another solution is to have nested describe to login_user first like this:

describe "something" do
  login_user
  describe "something 1" do
    #yourcode
  end

end

Upvotes: -1

Related Questions