Oleksandr Novik
Oleksandr Novik

Reputation: 738

Rspec test fails due to to redirection to a page for loggin in (Rails + Devise + Cancancan)

I am writing test for controllers in Rails:

require 'rails_helper'

RSpec.describe GoodsController, type: :controller do
  DatabaseCleaner.clean
  
  user = User.create(password: "12345678")
  user.save!

  describe "GET index" do
    it "renders the index template" do
      sign_in user
      get "index"
      expect(response).to render_template("index")
    end
  end

  DatabaseCleaner.clean
end

the GoodsController has this index action I want to test:

def index
  if params[:category_id] == nil
    @goods = Good.all
  else
    @goods = Good.where(category_id: params[:category_id])
  end
end

and when I run the test, I receive this error:

1) GoodsController GET index renders the index template
     Failure/Error: expect(response).to render_template("index")
       expecting <"index"> but was a redirect to <http://test.host/users/sign_in>
     # ./spec/controllers/goods_controller_spec.rb:12:in `block (3 levels) in <top (required)>'

I've added that sign_in user line, according to other answers in SO, but it didn't help. It still redirects to the logging page. How do I resolve this?

Upvotes: 0

Views: 786

Answers (2)

If you are going to have multiple tests that need the user to be signed in you could also wrap the sign_in in a before hook.

describe "GET index" do
  let(:user) { User.create(password: "12345678") }
  
  before do
    sign_in user
  end

  it "renders the index template" do
    get "index"
    expect(response).to render_template("index")
  end
 end

Upvotes: 0

razvans
razvans

Reputation: 3251

The user you create is not used by rspec when running the Examples (aka tests). It's just a variable inside a block that doesn't do anything useful.

When dealing with fixtures/factories you should either create them in before, let or inside the test itself (it block).

 describe "GET index" do
  let(:user) { User.create(password: "12345678") }

  it "renders the index template" do
    # OR, create it here before sign_in
    sign_in user
    get "index"
    expect(response).to render_template("index")
  end
 end

Not sure if you are using factory_bot, but you should look at it. Usually DatabaseCleaner is set up inside rails_helper, check this SO post for more details.

Upvotes: 1

Related Questions