require File.dirname(__FILE__) + '/assertions/action_pack_assertions'
require File.dirname(__FILE__) + '/assertions/active_record_assertions'
if defined?(RAILS_ROOT)
# Temporary hack for getting functional tests in Rails running under 1.8.2
class Object #:nodoc:
alias_method :require_without_load_path_reloading, :require
def require(file_name)
begin
require_without_load_path_reloading(file_name)
rescue Object => e
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) }
require_without_load_path_reloading(file_name)
end
end
end
end
module ActionController #:nodoc:
class Base
# Process a test request called with a +TestRequest+ object.
def self.process_test(request)
new.process_test(request)
end
def process_test(request) #:nodoc:
process(request, TestResponse.new)
end
end
class TestRequest < AbstractRequest #:nodoc:
attr_accessor :cookies
attr_accessor :query_parameters, :request_parameters, :path, :session, :env
attr_accessor :host, :remote_addr
def initialize(query_parameters = nil, request_parameters = nil, session = nil)
@query_parameters = query_parameters || {}
@request_parameters = request_parameters || {}
@session = session || TestSession.new
initialize_containers
initialize_default_values
super()
end
def reset_session
@session = {}
end
def port=(number)
@env["SERVER_PORT"] = number.to_i
end
def action=(action_name)
@query_parameters.update({ "action" => action_name })
@parameters = nil
end
# Used to check AbstractRequest's request_uri functionality.
# Disables the use of @path and @request_uri so superclass can handle those.
def set_REQUEST_URI(value)
@env["REQUEST_URI"] = value
@request_uri = nil
@path = nil
end
def request_uri=(uri)
@request_uri = uri
@path = uri.split("?").first
end
def request_uri
@request_uri || super()
end
def path
@path || super()
end
private
def initialize_containers
@env, @cookies = {}, {}
end
def initialize_default_values
@host = "test.host"
@request_uri = "/"
@remote_addr, @remote_ip = "127.0.0.1"
@env["SERVER_PORT"] = 80
end
end
class TestResponse < AbstractResponse #:nodoc:
# the class attribute ties a TestResponse to the assertions
class << self
attr_accessor :assertion_target
end
# initializer
def initialize
TestResponse.assertion_target=self# if TestResponse.assertion_target.nil?
super()
end
# the response code of the request
def response_code
headers['Status'][0,3].to_i rescue 0
end
# was the response successful?
def success?
response_code == 200
end
# was the URL not found?
def missing?
response_code == 404
end
# were we redirected?
def redirect?
(300..399).include?(response_code)
end
# was there a server-side error?
def server_error?
(500..599).include?(response_code)
end
# returns the redirection location or nil
def redirect_url
redirect? ? headers['location'] : nil
end
# does the redirect location match this regexp pattern?
def redirect_url_match?( pattern )
return false if redirect_url.nil?
p = Regexp.new(pattern) if pattern.class == String
p = pattern if pattern.class == Regexp
return false if p.nil?
p.match(redirect_url) != nil
end
# returns the template path of the file which was used to
# render this response (or nil)
def rendered_file(with_controller=false)
unless template.first_render.nil?
unless with_controller
template.first_render
else
template.first_render.split('/').last || template.first_render
end
end
end
# was this template rendered by a file?
def rendered_with_file?
!rendered_file.nil?
end
# a shortcut to the flash (or an empty hash if no flash.. hey! that rhymes!)
def flash
session['flash'] || {}
end
# do we have a flash?
def has_flash?
!session['flash'].empty?
end
# do we have a flash that has contents?
def has_flash_with_contents?
!flash.empty?
end
# does the specified flash object exist?
def has_flash_object?(name=nil)
!flash[name].nil?
end
# does the specified object exist in the session?
def has_session_object?(name=nil)
!session[name].nil?
end
# a shortcut to the template.assigns
def template_objects
template.assigns || {}
end
# does the specified template object exist?
def has_template_object?(name=nil)
!template_objects[name].nil?
end
# Returns the response cookies, converted to a Hash of (name => CGI::Cookie) pairs
# Example:
#
# assert_equal ['AuthorOfNewPage'], r.cookies['author'].value
def cookies
headers['cookie'].inject({}) { |hash, cookie| hash[cookie.name] = cookie; hash }
end
# Returns binary content (downloadable file), converted to a String
def binary_content
raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc)
require 'stringio'
sio = StringIO.new
begin
$stdout = sio
body.call
ensure
$stdout = STDOUT
end
sio.rewind
sio.read
end
end
class TestSession #:nodoc:
def initialize(attributes = {})
@attributes = attributes
end
def [](key)
@attributes[key]
end
def []=(key, value)
@attributes[key] = value
end
def session_id
""
end
def update() end
def close() end
def delete() @attributes = {} end
end
end
module Test
module Unit
class TestCase #:nodoc:
private
# execute the request and set/volley the response
def process(action, parameters = nil, session = nil, flash = nil)
@request.env['REQUEST_METHOD'] ||= "GET"
@request.action = action.to_s
@request.path_parameters = { :controller => @controller.class.controller_path }
@request.parameters.update(parameters) unless parameters.nil?
@request.session = ActionController::TestSession.new(session) unless session.nil?
@request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
@controller.process(@request, @response)
end
# execute the request simulating a specific http method and set/volley the response
%w( get post put delete head ).each do |method|
class_eval <<-EOV
def #{method}(action, parameters = nil, session = nil)
@request.env['REQUEST_METHOD'] = "#{method.upcase}"
process(action, parameters, session)
end
EOV
end
def follow_redirect
if @response.redirected_to[:controller]
raise "Can't follow redirects outside of current controller (#{@response.redirected_to[:controller]})"
end
get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys)
end
def assigns(name)
@response.template.assigns[name.to_s]
end
end
end
end