Search code examples
ruby-on-railsrubyrspecdevise

Testing an unauthenticated user Rspec/Devise


I have had a look around but maybe I'm not looking in the right places. I am trying to find out how to test that a user cannot access a page whose controller has:

before_filter :authenticate_user!

Ideally I would like to capture the devise message at the same time:

"you need to sign in or sign up before continuing"

I have this so far

require 'spec_helper'

describe CampaignsController do

  it "should not allow a user be able to access without being authenticated" do
    get :index
    response.should redirect_to(new_user_session_path)
  end

end

At present I get the error

Failure/Error: response.should redirect_to(new_user_session_path)
Expected response to be a <redirect>, but was <200>

Campaigns Controller

class CampaignsController < ApplicationController
  before_filter :authenticate_user! 

def index
  @campaigns = Campaign.all
end
end

In my spec helper I am calling the following

# Include Devise Test Helpers
config.include Devise::TestHelpers, :type => :controller
config.extend ControllerMacros, :type => :controller

controller_macros.rb

module ControllerMacros

def login_user
  before(:each) do
    @request.env["devise.mapping"] = Devise.mappings[:user]
    user = FactoryGirl.create(:user)
    sign_in user
  end
end
end

I'm not calling the login_user method at this stage, so would the spec_helper call this?

How do I approach this correctly?


Solution

  • At first look it seems ok. The problem could be caused if you run your entire suite, and depending on the place you call login_user it could add the before(:each) to all tests.

    I understand you want to minimise typing, but generally I prefer my tests to be a little more explicit: I want to see what is going on in the spec.

    So how I generally write this kind of test:

    describe HomeController do
      include Devise::TestHelpers
    
      context "when not signed in" do
        describe "GET 'index'" do
          it "redirects to sign in" do
            get 'index'
            response.should be_redirect
          end
        end
        describe "GET 'about'" do
          it "returns http success" do
            get 'about'
            response.should be_redirect
          end
        end
      end
    
      context "when signed in" do
        before do
          user = FactoryGirl.create(:user)
          sign_in(user)
        end
        describe 'GET :index' do
          it "returns http success" do
            get 'index'
            response.should be_success
          end
        end
        describe "GET 'about'" do
          it "returns http success" do
            get 'about'
            response.should be_success
          end
        end
      end
    end
    

    Yes, admitted: I am still fond of the old rspec syntax (using should), it reads much more natural to me.