I'm writing rspecs for my ruby on rails application, and I'm using google for my authentication. I had my specs all setup fine before I added auth, but now I need some way to test an authenticated user. Here is what one of my specs looks like.
require 'rails_helper'
RSpec.describe 'Test', type: :request do
it 'should return 200' do
get '/test'
expect(response).to have_http_status(:ok)
end
end
This is failing with a 401 as it rightfully should be.
I need to add the authentication information into the session variable so the controller can recognize that the user is logged in, but there doesn't seem to be a way to modify the session variable from rspec. I guess I could make a test google account and setup some helpers that would log me into a real google account, but it seems like there should be a better way to write tests. I've seen a couple of examples online, but most seem to be for older versions of rails.
I'm on Rails 7.0.4.3 and ruby 3.2.2
Edit: It occurs to me that I should probably include my auth code.
class ApplicationController < ActionController::Base
before_action :require_auth
private
def require_auth
user_id = session[:user_id]
if !user_id.present?
head :unauthorized
else
@auth_user = User.find(user_id)
if !@auth_user.present?
head :unauthorized
end
end
end
end
As far as I know there is no way of easily modifying session variables in the test setup for RSpec request specs unless you add the rack_session_access
gem or a similar solution.
One approach is to just mock the auth_user
object in the tests that require a logged in user.
class ApplicationController < ActionController::Base
before_action :require_auth
private
def auth_user
@auth_user ||= User.find_by(id: session[:user_id])
end
def require_auth
head(:unauthorized) unless auth_user.present?
end
end
# spec/support/test_macros.rb
module TestMacros
def log_in(user)
allow_any_instance_of(ApplicationController).to receive(:auth_user).and_return(user)
end
end
# spec/rails_helper.rb
RSpec.configure do |config|
config.include(TestMacros)
end
it 'should return 200' do
user = # create or fabricate user
log_in(user)
get '/test'
expect(response).to have_http_status(:ok)
end