aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/test/mock.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/test/mock.rb')
-rw-r--r--actionpack/lib/action_dispatch/test/mock.rb127
1 files changed, 127 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