Skip to content
This repository
Browse code

Allow file uploads in Integration Tests. Closes #11091 [RubyRedRick]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8978 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit cc5a957d2b57b1d7081abd6939396f32e7b4b204 1 parent 4ca170f
Michael Koziarski NZKoz authored
2  actionpack/CHANGELOG
... ... @@ -1,5 +1,7 @@
1 1 *SVN*
2 2
  3 +* Allow file uploads in Integration Tests. Closes #11091 [RubyRedRick]
  4 +
3 5 * Refactor partial rendering into a PartialTemplate class. [Pratik]
4 6
5 7 * Added that requests with JavaScript as the priority mime type in the accept header and no format extension in the parameters will be treated as though their format was :js when it comes to determining which template to render. This makes it possible for JS requests to automatically render action.js.rjs files without an explicit respond_to block [DHH]
50 actionpack/lib/action_controller/integration.rb
@@ -55,6 +55,9 @@ class Session
55 55 # A running counter of the number of requests processed.
56 56 attr_accessor :request_count
57 57
  58 + class MultiPartNeededException < Exception
  59 + end
  60 +
58 61 # Create and initialize a new +Session+ instance.
59 62 def initialize
60 63 reset!
@@ -294,6 +297,10 @@ def process(method, path, parameters = nil, headers = nil)
294 297
295 298 parse_result
296 299 return status
  300 + rescue MultiPartNeededException
  301 + boundary = "----------XnJLe9ZIbbGUYtzPQJ16u1"
  302 + status = process(method, path, multipart_body(parameters, boundary), (headers || {}).merge({"CONTENT_TYPE" => "multipart/form-data; boundary=#{boundary}"}))
  303 + return status
297 304 end
298 305
299 306 # Parses the result of the response and extracts the various values,
@@ -342,7 +349,9 @@ def name_with_prefix(prefix, name)
342 349 # Convert the given parameters to a request string. The parameters may
343 350 # be a string, +nil+, or a Hash.
344 351 def requestify(parameters, prefix=nil)
345   - if Hash === parameters
  352 + if TestUploadedFile === parameters
  353 + raise MultiPartNeededException
  354 + elsif Hash === parameters
346 355 return nil if parameters.empty?
347 356 parameters.map { |k,v| requestify(v, name_with_prefix(prefix, k)) }.join("&")
348 357 elsif Array === parameters
@@ -353,6 +362,45 @@ def requestify(parameters, prefix=nil)
353 362 "#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}"
354 363 end
355 364 end
  365 +
  366 + def multipart_requestify(params, first=true)
  367 + returning Hash.new do |p|
  368 + params.each do |key, value|
  369 + k = first ? CGI.escape(key.to_s) : "[#{CGI.escape(key.to_s)}]"
  370 + if Hash === value
  371 + multipart_requestify(value, false).each do |subkey, subvalue|
  372 + p[k + subkey] = subvalue
  373 + end
  374 + else
  375 + p[k] = value
  376 + end
  377 + end
  378 + end
  379 + end
  380 +
  381 + def multipart_body(params, boundary)
  382 + multipart_requestify(params).map do |key, value|
  383 + if value.respond_to?(:original_filename)
  384 + File.open(value.path) do |f|
  385 + <<-EOF
  386 +--#{boundary}\r
  387 +Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r
  388 +Content-Type: #{value.content_type}\r
  389 +Content-Length: #{File.stat(value.path).size}\r
  390 +\r
  391 +#{f.read}\r
  392 +EOF
  393 + end
  394 + else
  395 +<<-EOF
  396 +--#{boundary}\r
  397 +Content-Disposition: form-data; name="#{key}"\r
  398 +\r
  399 +#{value}\r
  400 +EOF
  401 + end
  402 + end.join("")+"--#{boundary}--\r"
  403 + end
356 404 end
357 405
358 406 # A module used to extend ActionController::Base, so that integration tests
47 actionpack/test/controller/integration_upload_test.rb
... ... @@ -0,0 +1,47 @@
  1 +require 'abstract_unit'
  2 +require 'action_controller/integration'
  3 +require 'action_controller/routing'
  4 +
  5 +unless defined? ApplicationController
  6 + class ApplicationController < ActionController::Base
  7 + end
  8 +end
  9 +
  10 +class UploadTestController < ActionController::Base
  11 + session :off
  12 +
  13 + def update
  14 + SessionUploadTest.last_request_type = ActionController::Base.param_parsers[request.content_type]
  15 + render :text => "got here"
  16 + end
  17 +end
  18 +
  19 +class SessionUploadTest < ActionController::IntegrationTest
  20 + FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart'
  21 +
  22 + class << self
  23 + attr_accessor :last_request_type
  24 + end
  25 +
  26 +
  27 + # def setup
  28 + # @session = ActionController::Integration::Session.new
  29 + # end
  30 + #
  31 + def test_post_with_upload
  32 + uses_mocha "test_post_with_upload" do
  33 + Dependencies.stubs(:load?).returns(false)
  34 + with_routing do |set|
  35 + set.draw do |map|
  36 + map.update 'update', :controller => "upload_test", :action => "update", :method => :post
  37 + end
  38 + path = "/update"
  39 + params = {:uploaded_data => fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg")}
  40 + headers = {:location => 'blah' }
  41 + post(path,params,headers)
  42 + assert_equal(:multipart_form, SessionUploadTest.last_request_type)
  43 + end
  44 + end
  45 +
  46 + end
  47 +end

0 comments on commit cc5a957

Please sign in to comment.
Something went wrong with that request. Please try again.