Devise – Test user timeout in feature/integration specs using Warden

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 :timeoutable.

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:

Include Warden::Test::Helpers to put Warden into test mode:

# settings_page_spec.rb

include Warden::Test::Helpers

or

# 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.

Leave a Reply

Your email address will not be published. Required fields are marked *