Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fields in multipart forms are not in correct order with Rack::Test driver #670

Closed
potager opened this issue Mar 19, 2012 · 2 comments
Closed

Comments

@potager
Copy link

potager commented Mar 19, 2012

Something that is not widely known is that HTML specify that multipart forms should be sent with the field order matching the order of the control in the page. Quoting http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2:

A "multipart/form-data" message contains a series of parts, each representing a successful control. The parts are sent to the processing agent in the same order the corresponding controls appear in the document stream.

The following diff adds a new spec to test this behaviour. It currently fails when testing the Rack::Test and works fine for the one using Selenium.

diff --git a/lib/capybara/spec/session.rb b/lib/capybara/spec/session.rb
index 7b14d02..beb4393 100644
--- a/lib/capybara/spec/session.rb
+++ b/lib/capybara/spec/session.rb
@@ -134,6 +134,22 @@ shared_examples_for "session" do
     addresses[1]["country"].should  == 'Ukraine'
   end

+  it 'should post multipart form fields in the right order' do
+    # Quoting <http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2>:
+    #   A "multipart/form-data" message contains a series of parts, each
+    #   representing a successful control. The parts are sent to the processing
+    #   agent in the same order the corresponding controls appear in the document
+    #   stream.
+    @session.visit '/form'
+    @session.fill_in 'multipart_z', :with => 'z'
+    # we leave `multipart_file` empty
+    @session.fill_in 'multipart_a', :with => 'a'
+    @session.click_button 'multipart_submit'
+
+    input = Nokogiri::HTML(@session.body).xpath("//pre[@id='results']").first.text
+    fields = input.scan(/^Content-Disposition: form-data; name="([^"]+)"/).map(&:first)
+    fields.should == %w{multipart_z multipart_file multipart_a multipart_submit}
+  end
 end


diff --git a/lib/capybara/spec/test_app.rb b/lib/capybara/spec/test_app.rb
index dcc25e4..422d821 100644
--- a/lib/capybara/spec/test_app.rb
+++ b/lib/capybara/spec/test_app.rb
@@ -151,6 +151,12 @@ class TestApp < Sinatra::Base
       'No files uploaded'
     end
   end
+
+  post '/multipart_input' do
+    input = request.env['rack.input']
+    input.rewind
+    '<pre id="results">' + input.read + '</pre>'
+  end
 end

 if __FILE__ == $0
diff --git a/lib/capybara/spec/views/form.erb b/lib/capybara/spec/views/form.erb
index f75f8b8..c587ca8 100644
--- a/lib/capybara/spec/views/form.erb
+++ b/lib/capybara/spec/views/form.erb
@@ -364,3 +364,19 @@
     <input type="submit" name="form[no_action]" value="No Action" />
   </p>
 </form>
+
+<form action="/multipart_input" method="post" enctype="multipart/form-data">
+  <!-- Be careful, the field order matters here. -->
+  <p>
+    <input type="text" name="multipart_z" id="multipart_z"/>
+  </p>
+  <p>
+    <input type="file" name="multipart_file" id="multipart_file"/>
+  </p>
+  <p>
+    <input type="text" name="multipart_a" id="multipart_a"/>
+  </p>
+  <p>
+    <input type="submit" name="multipart_submit" value="multipart_submit" />
+  </p>
+</form>

The issue should probably be solved in Rack::Test but testing this will help those who would like to implement new drivers.

@potager
Copy link
Author

potager commented Mar 19, 2012

Please note that this spec is actually green when using Ruby version 1.9.1 or later, due to Hash insertion order being preserved.

Although that is a really unusual setup, if the multipart_submit field is moved to the top of the form it will not be sent in the correct place. Exactly because of the "TO DO" item in lib/capybara/rack_test/form.rb:params.

@jnicklas
Copy link
Collaborator

I'm going to close this issue as "won't fix". Ruby 1.8 is on the way out, and this is a rather extreme edge case. As a workaround, use a different driver, or switch to Ruby 1.9.

@lock lock bot locked and limited conversation to collaborators Aug 17, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants