mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
When using rack-test 2, we no longer need to send NilUploadedFile to trigger multipart
This commit is contained in:
parent
6cba8b4b5a
commit
a3ff5514f4
9 changed files with 76 additions and 11 deletions
2
Gemfile
2
Gemfile
|
@ -7,6 +7,8 @@ gemspec
|
|||
|
||||
gem 'xpath', github: 'teamcapybara/xpath'
|
||||
|
||||
# gem 'rack-test', github: 'rack/rack-test'
|
||||
|
||||
group :doc do
|
||||
gem 'redcarpet', platforms: :mri
|
||||
end
|
||||
|
|
|
@ -31,11 +31,17 @@ class Capybara::RackTest::Browser
|
|||
request(last_request.fullpath, last_request.env)
|
||||
end
|
||||
|
||||
def submit(method, path, attributes)
|
||||
def submit(method, path, attributes, content_type: nil)
|
||||
path = request_path if path.nil? || path.empty?
|
||||
uri = build_uri(path)
|
||||
uri.query = '' if method.to_s.casecmp('get').zero?
|
||||
process_and_follow_redirects(method, uri.to_s, attributes, 'HTTP_REFERER' => referer_url)
|
||||
process_and_follow_redirects(
|
||||
method,
|
||||
uri.to_s,
|
||||
attributes,
|
||||
'HTTP_REFERER' => referer_url,
|
||||
'CONTENT_TYPE' => content_type
|
||||
)
|
||||
end
|
||||
|
||||
def follow(method, path, **attributes)
|
||||
|
|
|
@ -30,19 +30,31 @@ class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|||
|
||||
form_elements = native.xpath(form_elements_xpath).reject { |el| submitter?(el) && (el != button.native) }
|
||||
|
||||
form_elements.each_with_object(make_params) do |field, params|
|
||||
form_params = form_elements.each_with_object({}.compare_by_identity) do |field, params|
|
||||
case field.name
|
||||
when 'input', 'button' then add_input_param(field, params)
|
||||
when 'select' then add_select_param(field, params)
|
||||
when 'textarea' then add_textarea_param(field, params)
|
||||
end
|
||||
end
|
||||
|
||||
form_params.each_with_object(make_params) do |(name, value), params|
|
||||
merge_param!(params, name, value)
|
||||
end.to_params_hash
|
||||
|
||||
# form_elements.each_with_object(make_params) do |field, params|
|
||||
# case field.name
|
||||
# when 'input', 'button' then add_input_param(field, params)
|
||||
# when 'select' then add_select_param(field, params)
|
||||
# when 'textarea' then add_textarea_param(field, params)
|
||||
# end
|
||||
# end.to_params_hash
|
||||
end
|
||||
|
||||
def submit(button)
|
||||
action = button&.[]('formaction') || native['action']
|
||||
method = button&.[]('formmethod') || request_method
|
||||
driver.submit(method, action.to_s, params(button))
|
||||
driver.submit(method, action.to_s, params(button), content_type: native['enctype'])
|
||||
end
|
||||
|
||||
def multipart?
|
||||
|
@ -88,6 +100,8 @@ private
|
|||
|
||||
Capybara::RackTest::Node.new(driver, field).value.to_s
|
||||
when 'file'
|
||||
return if value.empty? && params.keys.include?(name) && Rack::Test::VERSION.to_f >= 2.0 # rubocop:disable Performance/InefficientHashSearch
|
||||
|
||||
if multipart?
|
||||
file_to_upload(value)
|
||||
else
|
||||
|
@ -96,7 +110,8 @@ private
|
|||
else
|
||||
value
|
||||
end
|
||||
merge_param!(params, name, value)
|
||||
# merge_param!(params, name, value)
|
||||
params[name] = value
|
||||
end
|
||||
|
||||
def file_to_upload(filename)
|
||||
|
@ -109,18 +124,23 @@ private
|
|||
end
|
||||
|
||||
def add_select_param(field, params)
|
||||
name = field['name']
|
||||
if field.has_attribute?('multiple')
|
||||
field.xpath('.//option[@selected]').each do |option|
|
||||
merge_param!(params, field['name'], (option['value'] || option.text).to_s)
|
||||
value = field.xpath('.//option[@selected]').map do |option|
|
||||
# merge_param!(params, field['name'], (option['value'] || option.text).to_s)
|
||||
(option['value'] || option.text).to_s
|
||||
end
|
||||
params[name] = value unless value.empty?
|
||||
else
|
||||
option = field.xpath('.//option[@selected]').first || field.xpath('.//option').first
|
||||
merge_param!(params, field['name'], (option['value'] || option.text).to_s) if option
|
||||
# merge_param!(params, field['name'], (option['value'] || option.text).to_s) if option
|
||||
params[name] = (option['value'] || option.text).to_s if option
|
||||
end
|
||||
end
|
||||
|
||||
def add_textarea_param(field, params)
|
||||
merge_param!(params, field['name'], field['_capybara_raw_value'].to_s.gsub(/\r?\n/, "\r\n"))
|
||||
# merge_param!(params, field['name'], field['_capybara_raw_value'].to_s.gsub(/\r?\n/, "\r\n"))
|
||||
params[field['name']] = field['_capybara_raw_value'].to_s.gsub(/\r?\n/, "\r\n")
|
||||
end
|
||||
|
||||
def submitter?(el)
|
||||
|
|
|
@ -55,6 +55,12 @@ Capybara::SpecHelper.spec '#attach_file' do
|
|||
expect(@session).to have_content('No file uploaded')
|
||||
end
|
||||
|
||||
it 'should send prior hidden field if no file submitted' do
|
||||
@session.click_button('Upload Empty With Hidden')
|
||||
expect(extract_results(@session)['document2']).to eq('hidden_field')
|
||||
expect(extract_content_type(@session)).to start_with('multipart/form-data;')
|
||||
end
|
||||
|
||||
it 'should send content type text/plain when uploading a text file' do
|
||||
@session.attach_file 'Single Document', with_os_path_separators(test_file_path)
|
||||
@session.click_button 'Upload Single'
|
||||
|
|
|
@ -122,6 +122,11 @@ module Capybara
|
|||
YAML.safe_load results, permitted_classes: perms
|
||||
end
|
||||
|
||||
def extract_content_type(session)
|
||||
expect(session).to have_xpath("//pre[@id='content_type']")
|
||||
Capybara::HTML(session.body).xpath("//pre[@id='content_type']").first.text
|
||||
end
|
||||
|
||||
def be_an_invalid_element_error(session)
|
||||
satisfy { |error| session.driver.invalid_element_errors.any? { |e| error.is_a? e } }
|
||||
end
|
||||
|
|
|
@ -256,12 +256,15 @@ class TestApp < Sinatra::Base
|
|||
|
||||
post '/form' do
|
||||
self.class.form_post_count += 1
|
||||
%(<pre id="results">#{params[:form].merge('post_count' => self.class.form_post_count).to_yaml}</pre>)
|
||||
%(
|
||||
<pre id="content_type">#{request.content_type}</pre>
|
||||
<pre id="results">#{params.fetch(:form, {}).merge('post_count' => self.class.form_post_count).to_yaml}</pre>
|
||||
)
|
||||
end
|
||||
|
||||
post '/upload_empty' do
|
||||
if params[:form][:file].nil?
|
||||
'Successfully ignored empty file field.'
|
||||
"Successfully ignored empty file field. Content type was #{request.content_type}"
|
||||
else
|
||||
'Something went wrong.'
|
||||
end
|
||||
|
|
|
@ -586,6 +586,19 @@ New line after and before textarea tag
|
|||
<p>
|
||||
</form>
|
||||
|
||||
<form action="/form" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="form[document2]" value="hidden_field"/>
|
||||
|
||||
<p>
|
||||
<label for="form_document">Document with hidden</label>
|
||||
<input type="file" name="form[document2]" id="form_document2"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="Upload Empty With Hidden"/>
|
||||
<p>
|
||||
</form>
|
||||
|
||||
<form action="/upload_multiple" method="post" enctype="multipart/form-data">
|
||||
<p>
|
||||
<label for="form_multiple_file_name">File Name</label>
|
||||
|
|
|
@ -15,6 +15,8 @@ Capybara::SpecHelper.run_specs TestClass.new, 'DSL', capybara_skip: %i[
|
|||
pending "Nokogiri doesn't support case insensitive CSS attribute matchers"
|
||||
when /#click_button should follow permanent redirects that maintain method/
|
||||
pending "Rack < 2 doesn't support 308" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')
|
||||
when /#attach_file with multipart form should send prior hidden field if no file submitted/
|
||||
skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ Capybara::SpecHelper.run_specs TestSessions::RackTest, 'RackTest', capybara_skip
|
|||
skip "Nokogiri doesn't support case insensitive CSS attribute matchers"
|
||||
when /#click_button should follow permanent redirects that maintain method/
|
||||
skip "Rack < 2 doesn't support 308" if Gem.loaded_specs['rack'].version < Gem::Version.new('2.0.0')
|
||||
when /#attach_file with multipart form should send prior hidden field if no file submitted/
|
||||
skip 'Rack-test < 2 needs an empty file to detect multipart form' if Gem.loaded_specs['rack-test'].version < Gem::Version.new('2.0.0')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -93,6 +95,12 @@ RSpec.describe Capybara::Session do # rubocop:disable RSpec/MultipleDescribes
|
|||
session.click_button('Upload Empty')
|
||||
expect(session.html).to include('Successfully ignored empty file field.')
|
||||
end
|
||||
|
||||
it 'should submit multipart even if no file is submitted' do
|
||||
session.visit('/form')
|
||||
session.click_button('Upload Empty')
|
||||
expect(session.html).to include('Content type was multipart/form-data;')
|
||||
end
|
||||
end
|
||||
|
||||
it 'should not submit an obsolete mime type' do
|
||||
|
|
Loading…
Reference in a new issue