Back to Repositories

Testing Custom Warden Strategy Implementation in Devise

This test suite validates custom Warden authentication strategies in Devise, specifically focusing on custom HTTP responses and headers. It demonstrates how to implement and test non-standard authentication responses in a Rails application.

Test Coverage Overview

The test suite covers custom Warden strategy implementation with specific focus on non-standard HTTP responses. Key areas tested include:

  • Custom status code (400) verification
  • Custom HTTP header implementation
  • Integration with Devise’s authentication flow
  • Warden strategy registration and cleanup

Implementation Analysis

The testing approach utilizes Devise’s controller test framework combined with Warden strategy integration. The implementation showcases pattern of temporary strategy registration for isolated testing, using setup/teardown hooks for clean test environment.

Technical patterns include:
  • Custom Warden strategy inheritance
  • Rack response manipulation
  • Controller test isolation
  • Dynamic strategy registration

Technical Details

Testing tools and configuration:
  • Devise::ControllerTestCase as base test class
  • Warden::Strategies::Base for strategy implementation
  • Devise::Test::ControllerHelpers for authentication testing
  • ActionController::Base for controller implementation
  • Rack::Response for custom HTTP response handling

Best Practices Demonstrated

The test suite exemplifies several testing best practices in authentication testing:

  • Proper test isolation through setup/teardown hooks
  • Explicit verification of response types and contents
  • Comprehensive header and status code checking
  • Clean separation of strategy and test concerns
  • Proper documentation of production vs testing behavior differences

heartcombo/devise

test/controllers/custom_strategy_test.rb

            
# frozen_string_literal: true

require 'test_helper'
require 'ostruct'
require 'warden/strategies/base'
require 'devise/test_helpers'

class CustomStrategyController < ActionController::Base
  def new
    warden.authenticate!(:custom_strategy)
  end
end

# These tests are to prove that a warden strategy can successfully
# return a custom response, including a specific status code and
# custom http response headers. This does work in production,
# however, at the time of writing this, the Devise test helpers do
# not recognise the custom response and proceed to calling the
# Failure App. This makes it impossible to write tests for a
# strategy that return a custom response with Devise.
class CustomStrategy < Warden::Strategies::Base
  def authenticate!
    custom_headers = { "X-FOO" => "BAR" }
    response = Rack::Response.new("BAD REQUEST", 400, custom_headers)
    custom! response.finish
  end
end

class CustomStrategyTest < Devise::ControllerTestCase
  tests CustomStrategyController

  include Devise::Test::ControllerHelpers

  setup do
    Warden::Strategies.add(:custom_strategy, CustomStrategy)
  end

  teardown do
    Warden::Strategies._strategies.delete(:custom_strategy)
  end

  test "custom strategy can return its own status code" do
    ret = get :new

    # check the returned response
    assert ret.is_a?(ActionDispatch::TestResponse)

    # check the saved response as well. This is purely so that the response is available to the testing framework
    # for verification. In production, the above array would be delivered directly to Rack.
    assert_response 400
  end

  test "custom strategy can return custom headers" do
    ret = get :new

    # check the returned response
    assert ret.is_a?(ActionDispatch::TestResponse)

    # check the saved response headers as well.
    assert_equal 'BAR', response.headers['X-FOO']
  end
end