0
votes

I have used devise gem in rails to authenticate the user.I need to write test cases for checking whether a use is signed in or not using Rspec. Only user signed in will have the rights to access the posts index page.It is perfectly for signed in user in the Rspec. But for signed out user i have tried few steps but I cant get it right.I have used Warden for simple authentication for testing purpose.My post controller spec for Signed out user is :

describe "Unauthorized Access" do
    let(:user) {create(:user)}
    it "User tries to view post after Sign Out" do
      get :index
      expect(response).to have_http_status 401
    end
  end

Warden helper in the spec folder.

RSpec.shared_context "api request global before and after hooks" do
  before(:each) do
    Warden.test_mode!
  end

  after(:each) do
    Warden.test_reset!
  end
end

RSpec.shared_context "api request authentication helper methods" do
  def sign_in(user)
    login_as(user, scope: :users)
  end

  def sign_out
    logout(:users)
  end
end
When I click sign out button it is redirected to the log in page and the rails log show the log like this

Started GET "/" for 127.0.0.1 at 2018-09-05 11:33:10 +0530
Processing by PostsController#index as HTML
Completed 401 Unauthorized in 2ms (ActiveRecord: 0.0ms)


Started GET "/users/sign_in" for 127.0.0.1 at 2018-09-05 11:33:10 +0530
Processing by Devise::SessionsController#new as HTML
  Rendering devise/sessions/new.html.erb within layouts/application
  Rendered devise/shared/_links.html.erb (0.9ms)
  Rendered devise/sessions/new.html.erb within layouts/application (5.0ms)
Completed 200 OK in 69ms (Views: 67.9ms | ActiveRecord: 0.0ms)
But when I run the tests the rspec console showing error.

expected the response to have status code 401 but it was 302

  0) PostsController Unauthorized Access User tries to view post after Sign Out
     Failure/Error: expect(response).to have_http_status 401
       expected the response to have status code 401 but it was 302
     # ./spec/controllers/posts_controller_spec.rb:150:in `block (3 levels) in <top (required)>'
Rspec log

  (0.1ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
   (0.4ms)  begin transaction
Processing by PostsController#index as HTML
Completed 401 Unauthorized in 8ms (ActiveRecord: 0.0ms)
   (0.1ms)  rollback transaction
1
Why are you expecting a status 401?Mohd Anas
What are you trying to test, as per your test, your signing in the user and logging out and the response is obviously 200, because both the request is successful.Kedarnag Mukanahallipatna
You should be testing for if you can view the post, and check if the user is logged in, if not, then check response status for 401. If you look at the log, it says when you tried to list all the posts, when the user was not logged in it responded with Completed 401 Unauthorized in 2ms. You should be testing posts controller's index action.Kedarnag Mukanahallipatna

1 Answers

0
votes

You should be testing in the following manner, make changes as per your requirement.

describe PostsController do

  describe "Index" do

    it "should allow user to view the list of posts" do
      get :index, {}, sign_in(@user)
      expect(response).to redirect_to(posts_path)
    end

    it "should not list posts if the user is not logged in" do
      get :index
      expect(response.status).to eq(302)
      expect(response).to redirect_to(new_user_sessions_path)
    end
  end

end

Now what this test would do, when it runs it'll call your controller, assuming you have put authenticate_user!, it'll check if the user is logged in or not to view the list. Otherwise, the action will return 401.

You can try the following as well

  RSpec.describe "Posts", :type => :request do
    context "Index" do
      it 'should return 401 when not logged in' do
        sign_out user
        get posts_path
        expect(response).to have_http_status(302)
        follow_redirect!
        expect(response).to have_http_status(401)
      end
    end
  end