Fixes issue with multipart forms being submitted as x-www-form-urlencoded when they contain an empty file field
This commit is contained in:
parent
b022ca9926
commit
29898295dc
|
@ -97,6 +97,21 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|||
end
|
||||
|
||||
class Form < Node
|
||||
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
|
||||
# the class specifically when determing whether to consturct the request as multipart.
|
||||
# That check should be based solely on the form element's 'enctype' attribute value,
|
||||
# which should probably be provided to Rack::Test in its non-GET request methods.
|
||||
class NilUploadedFile < Rack::Test::UploadedFile
|
||||
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
|
||||
end
|
||||
|
||||
def params(button)
|
||||
params = {}
|
||||
|
||||
|
@ -122,16 +137,19 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|||
end
|
||||
end
|
||||
native.xpath(".//input[not(@disabled) and @type='file']").map do |input|
|
||||
unless input['value'].to_s.empty?
|
||||
if multipart?
|
||||
content_type = MIME::Types.type_for(input['value'].to_s).first.to_s
|
||||
file = Rack::Test::UploadedFile.new(input['value'].to_s, content_type)
|
||||
file = \
|
||||
if (value = input['value']).to_s.empty?
|
||||
NilUploadedFile.new
|
||||
else
|
||||
content_type = MIME::Types.type_for(value).first.to_s
|
||||
Rack::Test::UploadedFile.new(value, content_type)
|
||||
end
|
||||
merge_param!(params, input['name'].to_s, file)
|
||||
else
|
||||
merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
|
||||
end
|
||||
end
|
||||
end
|
||||
merge_param!(params, button[:name], button[:value] || "") if button[:name]
|
||||
params
|
||||
end
|
||||
|
|
|
@ -77,6 +77,14 @@ class TestApp < Sinatra::Base
|
|||
'<pre id="results">' + params[:form].to_yaml + '</pre>'
|
||||
end
|
||||
|
||||
post '/upload_empty' do
|
||||
if params[:form][:file].nil?
|
||||
'Successfully ignored empty file field.'
|
||||
else
|
||||
'Something went wrong.'
|
||||
end
|
||||
end
|
||||
|
||||
post '/upload' do
|
||||
begin
|
||||
buffer = []
|
||||
|
|
|
@ -250,6 +250,17 @@
|
|||
<p>
|
||||
</form>
|
||||
|
||||
<form action="/upload_empty" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<label for="form_file_name">File Name</label>
|
||||
<input type="file" name="form[file]" id="form_file"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Upload Empty"/>
|
||||
<p>
|
||||
</form>
|
||||
|
||||
<form action="/upload" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<label for="form_file_name">File Name</label>
|
||||
|
|
|
@ -26,6 +26,16 @@ describe Capybara::Session do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#attach_file" do
|
||||
context "with multipart form" do
|
||||
it "should submit an empty form-data section if no file is submitted" do
|
||||
@session.visit("/form")
|
||||
@session.click_button("Upload Empty")
|
||||
@session.body.should include('Successfully ignored empty file field.')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_should_behave_like "session"
|
||||
it_should_behave_like "session without javascript support"
|
||||
it_should_behave_like "session with headers support"
|
||||
|
|
Loading…
Reference in New Issue