Created
December 23, 2014 18:50
-
-
Save nanofi/c9a511be02ce9c972f0f to your computer and use it in GitHub Desktop.
Controller test helpers for `rails_warden`. Almost of this code is extracted from Devise::TestHelpers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ControllerHelpers | |
def self.included(base) | |
base.class_eval do | |
setup :setup_controller_for_warden, :warden if respond_to?(:setup) | |
end | |
end | |
def process(*) | |
_catch_warden {super} || @response | |
end | |
def setup_controller_for_warden | |
@request.env['action_controller.instance'] = @controller | |
end | |
def warden | |
@warden ||= | |
begin | |
middleware = Rails.application.config.middleware.detect{|m| m.name == 'RailsWarden::Manager'} | |
manager = Warden::Manager.new(nil, &middleware.block) | |
@request.env['warden'] = Warden::Proxy.new(@request.env, manager) | |
end | |
end | |
protected | |
# Catch warden continuations and handle like the middleware would. | |
# Returns nil when interrupted, otherwise the normal result of the block. | |
def _catch_warden(&block) | |
result = catch(:warden, &block) | |
env = @controller.request.env | |
result ||= {} | |
# Set the response. In production, the rack result is returned | |
# from Warden::Manager#call, which the following is modelled on. | |
case result | |
when Array | |
if result.first == 401 && intercept_401?(env) # does this happen during testing? | |
_process_unauthenticated(env) | |
else | |
result | |
end | |
when Hash | |
_process_unauthenticated(env, result) | |
else | |
result | |
end | |
end | |
def _process_unauthenticated(env, options = {}) | |
options[:action] ||= :unauthenticated | |
proxy = env['warden'] | |
result = options[:result] || proxy.result | |
ret = | |
case result | |
when :redirect | |
body = proxy.message || "You are being redirected to #{proxy.headers['Location']}" | |
[proxy.status, proxy.headers, [body]] | |
when :custom | |
proxy.custom_response | |
else | |
env["PATH_INFO"] = "/#{options[:action]}" | |
env["warden.options"] = options | |
Warden::Manager._run_callbacks(:before_failure, env, options) | |
status, headers, body = warden.config.failure_app.call(env).to_a | |
@controller.response.headers.merge!(headers) | |
@controller.send :render, status: status, text: response.body, | |
content_type: headers["Content-Type"], location: headers["Location"] | |
nil # causes process return @response | |
end | |
# ensure that the controller response is set up. In production, this is | |
# not necessary since warden returns the results to rack. However, at | |
# testing time, we want the response to be available to the testing | |
# framework to verify what would be returned to rack. | |
if ret.is_a?(Array) | |
# ensure the controller response is set to our response. | |
@controller.response ||= @response | |
@response.status = ret.first | |
@response.headers = ret.second | |
@response.body = ret.third | |
end | |
ret | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment