aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-04-24 20:24:03 -0500
committerJoshua Peek <josh@joshpeek.com>2009-04-24 20:24:54 -0500
commitdd2ed32418a74ca9126834f98a1b0bca926c0c4f (patch)
tree5a9983b3c83148fd7bac98cdaee18355cd3a37aa /actionpack/lib/action_dispatch
parentcbcc0ca57b0ea713d7d32364b599d88f2bef6d92 (diff)
downloadrails-dd2ed32418a74ca9126834f98a1b0bca926c0c4f.tar.gz
rails-dd2ed32418a74ca9126834f98a1b0bca926c0c4f.tar.bz2
rails-dd2ed32418a74ca9126834f98a1b0bca926c0c4f.zip
Start to integrate some of the features in Rack::Test.
Eventually commit ActionDispatch::Test::MockRequest and ActionDispatch::Test:: UploadedFile upstream.
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/test/mock.rb127
-rw-r--r--actionpack/lib/action_dispatch/test/uploaded_file.rb33
2 files changed, 160 insertions, 0 deletions
diff --git a/actionpack/lib/action_dispatch/test/mock.rb b/actionpack/lib/action_dispatch/test/mock.rb
new file mode 100644
index 0000000000..86269fad01
--- /dev/null
+++ b/actionpack/lib/action_dispatch/test/mock.rb
@@ -0,0 +1,127 @@
+module ActionDispatch
+ module Test
+ class MockRequest < Rack::MockRequest
+ MULTIPART_BOUNDARY = "----------XnJLe9ZIbbGUYtzPQJ16u1"
+
+ class << self
+ def env_for(path, opts)
+ headers = opts.delete(:headers)
+
+ method = (opts[:method] || opts["REQUEST_METHOD"]).to_s.upcase
+ opts[:method] = opts["REQUEST_METHOD"] = method
+
+ path = "/#{path}" unless path[0] == ?/
+ uri = URI.parse(path)
+ uri.host ||= "example.org"
+
+ if URI::HTTPS === uri
+ opts.update("SERVER_PORT" => "443", "HTTPS" => "on")
+ end
+
+ if method == "POST" && !opts.has_key?(:input)
+ opts["CONTENT_TYPE"] = "application/x-www-form-urlencoded"
+
+ multipart = (opts[:params] || {}).any? do |k, v|
+ UploadedFile === v
+ end
+
+ if multipart
+ opts[:input] = multipart_body(opts.delete(:params))
+ opts["CONTENT_LENGTH"] ||= opts[:input].length.to_s
+ opts["CONTENT_TYPE"] = "multipart/form-data; boundary=#{MULTIPART_BOUNDARY}"
+ else
+ params = opts.delete(:params)
+ opts[:input] = case params
+ when Hash then requestify(params)
+ when nil then ""
+ else params
+ end
+ end
+ end
+
+ params = opts[:params] || {}
+ if params.is_a?(String)
+ if method == "GET"
+ uri.query = params
+ else
+ opts[:input] = params
+ end
+ else
+ params.update(::Rack::Utils.parse_query(uri.query))
+ uri.query = requestify(params)
+ end
+
+ env = ::Rack::MockRequest.env_for(uri.to_s, opts)
+
+ (headers || {}).each do |key, value|
+ key = key.to_s.upcase.gsub(/-/, "_")
+ key = "HTTP_#{key}" unless env.has_key?(key) || key =~ /^HTTP_/
+ env[key] = value
+ end
+
+ env
+ end
+
+ private
+ def requestify(value, prefix = nil)
+ case value
+ when Array
+ value.map do |v|
+ requestify(v, "#{prefix}[]")
+ end.join("&")
+ when Hash
+ value.map do |k, v|
+ requestify(v, prefix ? "#{prefix}[#{::Rack::Utils.escape(k)}]" : ::Rack::Utils.escape(k))
+ end.join("&")
+ else
+ "#{prefix}=#{::Rack::Utils.escape(value)}"
+ end
+ end
+
+ def multipart_requestify(params, first=true)
+ p = Hash.new
+
+ params.each do |key, value|
+ k = first ? key.to_s : "[#{key}]"
+
+ if Hash === value
+ multipart_requestify(value, false).each do |subkey, subvalue|
+ p[k + subkey] = subvalue
+ end
+ else
+ p[k] = value
+ end
+ end
+
+ return p
+ end
+
+ def multipart_body(params)
+ multipart_requestify(params).map do |key, value|
+ if value.respond_to?(:original_filename)
+ ::File.open(value.path, "rb") do |f|
+ f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding)
+
+ <<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{key}"; filename="#{::Rack::Utils.escape(value.original_filename)}"\r
+Content-Type: #{value.content_type}\r
+Content-Length: #{::File.stat(value.path).size}\r
+\r
+#{f.read}\r
+EOF
+ end
+ else
+<<-EOF
+--#{MULTIPART_BOUNDARY}\r
+Content-Disposition: form-data; name="#{key}"\r
+\r
+#{value}\r
+EOF
+ end
+ end.join("")+"--#{MULTIPART_BOUNDARY}--\r"
+ end
+ end
+ end
+ end
+end
diff --git a/actionpack/lib/action_dispatch/test/uploaded_file.rb b/actionpack/lib/action_dispatch/test/uploaded_file.rb
new file mode 100644
index 0000000000..0ac7db4863
--- /dev/null
+++ b/actionpack/lib/action_dispatch/test/uploaded_file.rb
@@ -0,0 +1,33 @@
+require "tempfile"
+
+module ActionDispatch
+ module Test
+ class UploadedFile
+ # The filename, *not* including the path, of the "uploaded" file
+ attr_reader :original_filename
+
+ # The content type of the "uploaded" file
+ attr_accessor :content_type
+
+ def initialize(path, content_type = "text/plain", binary = false)
+ raise "#{path} file does not exist" unless ::File.exist?(path)
+ @content_type = content_type
+ @original_filename = ::File.basename(path)
+ @tempfile = Tempfile.new(@original_filename)
+ @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding)
+ @tempfile.binmode if binary
+ FileUtils.copy_file(path, @tempfile.path)
+ end
+
+ def path
+ @tempfile.path
+ end
+
+ alias_method :local_path, :path
+
+ def method_missing(method_name, *args, &block) #:nodoc:
+ @tempfile.__send__(method_name, *args, &block)
+ end
+ end
+ end
+end