diff --git a/lib/capybara/driver/rack_test_driver.rb b/lib/capybara/driver/rack_test_driver.rb index ceb1f06c..af34ea16 100644 --- a/lib/capybara/driver/rack_test_driver.rb +++ b/lib/capybara/driver/rack_test_driver.rb @@ -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,14 +137,17 @@ 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) - merge_param!(params, input['name'].to_s, file) - else - merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s)) - end + if multipart? + 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 merge_param!(params, button[:name], button[:value] || "") if button[:name] diff --git a/lib/capybara/spec/test_app.rb b/lib/capybara/spec/test_app.rb index 2a659390..dc851dbb 100644 --- a/lib/capybara/spec/test_app.rb +++ b/lib/capybara/spec/test_app.rb @@ -77,6 +77,14 @@ class TestApp < Sinatra::Base '
' + params[:form].to_yaml + '
' 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 = [] diff --git a/lib/capybara/spec/views/form.erb b/lib/capybara/spec/views/form.erb index 5825ff90..a98b80c5 100644 --- a/lib/capybara/spec/views/form.erb +++ b/lib/capybara/spec/views/form.erb @@ -250,6 +250,17 @@

+

+

+ + +

+ +

+ +

+

+

diff --git a/spec/session/rack_test_session_spec.rb b/spec/session/rack_test_session_spec.rb index 7330ff3b..5a54a368 100644 --- a/spec/session/rack_test_session_spec.rb +++ b/spec/session/rack_test_session_spec.rb @@ -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"