dominikduda dominikduda - 7 months ago 11
Ruby Question

Rails and devise - testing controller when signed in and signed out

So I want to test controller which is using devise.

require 'rails_helper'

describe ArticlesController do
before(:all) { @article = FactoryGirl.create(:article) }

sign_in_admin

describe 'GET new' do
let(:call_request) { get :new }

before { call_request }

context 'admin signed in' do
it { is_expected.to respond_with :ok }
end

context 'admin signed out' do
it { is_expected.to respond_with 302 }
end
end
end


I followed this guide from devise wiki. So I created ControllerMacros module as you can see here:

module ControllerMacros
def sign_in_admin
before(:each) do
@request.env['devise.mapping'] = Devise.mappings[:admin]
@admin = FactoryGirl.create(:admin)
sign_in @admin
end
end
end


And included it, and other needed things to rails_helper:

require_relative 'support/controller_macros.rb'

RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.extend ControllerMacros, type: :controller
(...)


Here is admin factory:

FactoryGirl.define do
factory :admin do
email 'email@email.com'
password 'password'
end
end


But now I don't know how to sign out admin? As sign_in_admin is executing before each test, but I need to sign admin out for some of the tests. What is the best way to test this controller with signed in/out admin?

btw I'm kinda new to testing

Answer

Devise provides some helper methods for testing, including login_user which takes a user, so you shouldn't need to create the sign_in_admin function. Also by using before(:all) at the top of the block, you've signed in the admin for the entire suite of specs.

Use before(:each) within the individual contexts that you want a signed_in_admin.

describe ArticlesController do
  describe 'GET new' do
    let(:call_request) { get :new }
    let(:admin_user) { FactoryGirl.create(:admin) }

    before { call_request }

    context 'admin signed in' do
      sign_in(admin_user)
      it { is_expected.to respond_with :ok }
    end

    context 'admin not signed in' do
      it { is_expected.to respond_with 302 }
    end
  end
end