You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In system tests, we've been stubbing our SSO calls to WorkOS and then visiting our sso callback action. That action ends up calling auto_login. This approach works well but ends up in an extra round trip to the server on every spec. With that in mind, I came up with a way to authenticate in the test env when the first "real" request to a page happens.
The approach is,
Setting a "global" login user in the test env when calling login
Setting the same session keys, as Sorcery sets, in middleware (and clearing the login user variable)
I tried many many ways to set session before the request, use query params, set headers, page.driver.browser.execute_cdp with "Network.setCookie", setting localstorage, etc. No luck on any of those approaches because capybara fires up the browser at data:, and that url prevents setting anything (or persisting anything) on the actual domain the test is hitting.
The singleton approach is never ideal but in the test environment, it works well. It's a simple and easily manageable way to pass around the "global user" that should be logged in and easy to clear out before the next test. This saves us about ~0.3 seconds per test run by avoiding the server roundtrip.
In spec/support/auth_support.rb
# Singleton class to store the login user which is used in TestUserAuthMiddleware# to set the current user in the request.# In tests, this saves a full round trip to the server to authenticate the user.classTestLoginUserincludeSingletonattr_accessor(:login_user)defclear_user@login_user=nilendendmoduleAuthSupportdeflogin(user=create(:user))TestLoginUser.instance.login_user=userendendRSpec.configuredo |config|
config.include(AuthSupport,type: ->(type){%i[systemrequest].include?(type)})# Clear the login user before each testconfig.before(:each,type: ->(type){%i[systemrequest].include?(type)})doTestLoginUser.instance.clear_userendend
In lib/middleware/test_user_auth_middleware.rb
# Intercept the request and set the user_id in the session.# In tests, this saves a full round trip to the server to authenticate the user.classTestUserAuthMiddlewareattr_reader(:app)definitialize(app)@app=appenddefcall(env)login_user=TestLoginUser.instance.login_useriflogin_user.present?env["rack.session"][:user_id]=login_user.idTestLoginUser.instance.clear_userendapp.call(env)endend
Answering the call here: https://github.com/Sorcery/sorcery/wiki/Testing-Rails#feature-tests-w-selenium-or-webkit
In system tests, we've been stubbing our SSO calls to WorkOS and then visiting our sso callback action. That action ends up calling
auto_login
. This approach works well but ends up in an extra round trip to the server on every spec. With that in mind, I came up with a way to authenticate in the test env when the first "real" request to a page happens.The approach is,
login
session
keys, as Sorcery sets, in middleware (and clearing the login user variable)This approach is inspired by
Warden
's on_next_request hook and rack_session_access middleware.I tried many many ways to set session before the request, use query params, set headers,
page.driver.browser.execute_cdp
with"Network.setCookie"
, setting localstorage, etc. No luck on any of those approaches because capybara fires up the browser atdata:,
and that url prevents setting anything (or persisting anything) on the actual domain the test is hitting.The singleton approach is never ideal but in the test environment, it works well. It's a simple and easily manageable way to pass around the "global user" that should be logged in and easy to clear out before the next test. This saves us about ~0.3 seconds per test run by avoiding the server roundtrip.
In
spec/support/auth_support.rb
In
lib/middleware/test_user_auth_middleware.rb
In
config/environments/test.rb
Let me know what you think!
The text was updated successfully, but these errors were encountered: