Devise is an excellent framework for strapping authentication features onto your Rails app. One of the very handy modules that provides session timeout features is
Being a responsible test-driven developer, you start writing tests to ensure your application behaves correctly when the User tries to perform an action that is not allowed after their session timed out. But how to simulate that 30 minutes have gone by? (default
config.timeout_in = 30.minutes)
A brief search of the nets offers a few pointers to overriding the Devise
User.timedout? method but that doesn’t really help our feature spec when ensuring that User was redirected to the Login page upon performing a session-protected action.
Here’s one solution:
Devise is built on top of Warden, so let’s see if we can’t leverage Warden’s test helpers to simulate our timed out user:
Warden::Test::Helpers to put Warden into test mode:
# settings_page_spec.rb include Warden::Test::Helpers
# spec/rails_helper.rb RSpec.configure do |config| ... config.include Warden::Test::Helpers, type: :feature end
Modify the Rack proxy via
Warden.on_next_request in order to simulate that the User has been timed out by Devise::SessionsController:
# settings_page_spec.rb it 'does not allow updating password' do expect(current_path).to eq(user_settings_path(user)) clink_link 'Manage Password' expect(page).to have_button('Update Password') Warden.on_next_request do |proxy| proxy.set_user(nil) click_button 'Update Password' expect(current_path).to eq(login_path) end end
We now have a method of simulating timed out behavior that does not involve playing games with time elapsed.