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
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)
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)>'
(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
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