1
0
Fork 0
mirror of https://github.com/heartcombo/devise.git synced 2022-11-09 12:18:31 -05:00
heartcombo--devise/test/controllers/custom_strategy_test.rb

92 lines
3.3 KiB
Ruby

require 'test_helper'
require 'ostruct'
require 'warden/strategies/base'
require 'devise/test_helpers'
class MyController < DeviseController
end
class CustomStrategyTest < ActionController::TestCase
tests MyController
include Devise::TestHelpers
# 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.
#
# The code this test needs to verify is in Devise::TestHelpers#_catch_warden (which appears to have no other test
# coverage at this point.) The functionality of this function should mirror Warden::Manager#call(env) and
# Warden::Manager#process_unauthenticated which correctly detects the custom response when set by a strategy.
#
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
# call the custom strategy, returning the rack result array
def call_custom(env_params={})
request.env ||= {}
request.env.merge! ({
'REQUEST_URI' => 'http://test.host/',
'HTTP_HOST' => 'test.host',
'REQUEST_METHOD' => 'GET',
'warden.options' => { :scope => :user },
'rack.session' => {},
'action_dispatch.request.formats' => Array(env_params.delete('formats') || Mime::HTML),
'rack.input' => "",
})
request.env.merge!(env_params)
env = request.env
# create a strategy instance
strategy = CustomStrategy.new env, :user
# processing a test request eventually calls _catch_warden:
ret = _catch_warden do
# when a controller action is triggered, its before filter would require authentication. Devise uses
# warden to execute the strategies.
# simulate its selection as the winning strategy (the custom response is read from .winning_strategy)
warden.winning_strategy = strategy
# And then the strategy is executed:
strategy.authenticate!
# after the strategy executes, halt! has been called (from in custom!) above which eventually results in
# the :warden symbol being thrown, which is caught in Devise::TestHelpers#_catch_warden
throw :warden
end
# after this point, @response should be set to the custom response when triggered by a custom strategy, or
# the response of the FailureApp as normal.
ret
end
test "custom strategy can return its own status code" do
ret = call_custom
# check the returned rack array
assert ret.is_a?(Array)
assert_equal 400, ret.first
# no need to test the saved response yet, that should be set by the correct processing of an action.
end
test "custom strategy can return custom headers" do
ret = call_custom
# check the returned rack array
assert ret.is_a?(Array)
assert_equal ret.third['X-FOO'], 'BAR'
# no need to test the saved response yet, that should be set by the correct processing of an action.
end
end