Skip to content

Commit

Permalink
Add support for old versions of Capybara::RackTest::Form::NilUploaded…
Browse files Browse the repository at this point in the history
…File

Capybara subclasses Rack::Test::UploadedFile, overrides initialize
and redefines a bunch of methods.  This is a terrible approach,
but as one of the goals is to keep capybara working with rack-test,
this hack is needed for compatibility.

Note that Capybara master already defines set_encoding and append_to,
so this is only needed for Capybara 3.37.1 and older.

Fixes #301
  • Loading branch information
jeremyevans committed May 26, 2022
1 parent 5116c46 commit cf9d2e0
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
7 changes: 5 additions & 2 deletions lib/rack/test/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ def build_primitive_part(parameter_name, value)

# Return the multipart fragment for a parameter that is a file upload.
def build_file_part(parameter_name, uploaded_file)
uploaded_file.set_encoding(Encoding::BINARY)
buffer = String.new
buffer << (<<-EOF)
--#{MULTIPART_BOUNDARY}\r
Expand All @@ -134,7 +133,11 @@ def build_file_part(parameter_name, uploaded_file)
content-length: #{uploaded_file.size}\r
\r
EOF
uploaded_file.append_to(buffer)
# Handle old versions of Capybara::RackTest::Form::NilUploadedFile
if uploaded_file.respond_to?(:set_encoding)
uploaded_file.set_encoding(Encoding::BINARY)
uploaded_file.append_to(buffer)
end
buffer << "\r\n"
end
end
Expand Down
33 changes: 33 additions & 0 deletions spec/rack/test/utils_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,39 @@
params['files'][:tempfile].read.must_equal files.read
end

it 'handles uploaded files not responding to set_encoding as empty' do
# Capybara::RackTest::Form::NilUploadedFile
c = Class.new(Rack::Test::UploadedFile) do
def initialize
@empty_file = Tempfile.new('nil_uploaded_file')
@empty_file.close
end

def original_filename; ''; end
def content_type; 'application/octet-stream'; end
def path; @empty_file.path; end
def size; 0; end
def read; ''; end
def respond_to?(m, *a)
return false if m == :set_encoding
super(m, *a)
end
end

data = Rack::Test::Utils.build_multipart('submit-name' => 'Larry', 'files' => c.new)
options = {
'CONTENT_TYPE' => "multipart/form-data; boundary=#{Rack::Test::MULTIPART_BOUNDARY}",
'CONTENT_LENGTH' => data.length.to_s,
:input => StringIO.new(data)
}
env = Rack::MockRequest.env_for('/', options)
params = Rack::Multipart.parse_multipart(env)
params['submit-name'].must_equal 'Larry'
params['files'].must_be_nil
data.must_include 'content-disposition: form-data; name="files"; filename=""'
data.must_include 'content-length: 0'
end

it 'builds multipart bodies from array of files' do
files = [Rack::Test::UploadedFile.new(multipart_file('foo.txt')), Rack::Test::UploadedFile.new(multipart_file('bar.txt'))]
data = Rack::Test::Utils.build_multipart('submit-name' => 'Larry', 'files' => files)
Expand Down

0 comments on commit cf9d2e0

Please sign in to comment.