2016-03-07 19:52:19 -05:00
|
|
|
# frozen_string_literal: true
|
2018-01-08 15:23:54 -05:00
|
|
|
|
2011-04-05 11:42:12 -04:00
|
|
|
class Capybara::RackTest::Form < Capybara::RackTest::Node
|
|
|
|
# This only needs to inherit from Rack::Test::UploadedFile because Rack::Test checks for
|
2014-03-19 19:28:26 -04:00
|
|
|
# the class specifically when determining whether to construct the request as multipart.
|
2011-04-05 11:42:12 -04:00
|
|
|
# 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
|
2018-07-10 17:18:39 -04:00
|
|
|
@empty_file = Tempfile.new('nil_uploaded_file')
|
2011-04-05 11:42:12 -04:00
|
|
|
@empty_file.close
|
|
|
|
end
|
|
|
|
|
2018-07-10 17:18:39 -04:00
|
|
|
def original_filename; ''; end
|
|
|
|
def content_type; 'application/octet-stream'; end
|
2011-04-05 11:42:12 -04:00
|
|
|
def path; @empty_file.path; end
|
2017-11-19 15:52:03 -05:00
|
|
|
def size; 0; end
|
2018-07-10 17:18:39 -04:00
|
|
|
def read; ''; end
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def params(button)
|
2015-10-28 16:26:45 -04:00
|
|
|
params = make_params
|
2013-02-13 19:01:51 -05:00
|
|
|
|
2018-01-08 15:23:54 -05:00
|
|
|
form_element_types = %i[input select textarea]
|
2018-08-20 19:46:31 -04:00
|
|
|
form_elements_xpath = XPath.generate do |xp|
|
|
|
|
xpath = xp.descendant(*form_element_types).where(!xp.attr(:form))
|
|
|
|
xpath += xp.anywhere(*form_element_types).where(xp.attr(:form) == native[:id]) if native[:id]
|
|
|
|
xpath.where(!xp.attr(:disabled))
|
2013-02-13 19:01:51 -05:00
|
|
|
end.to_s
|
2015-09-29 17:43:48 -04:00
|
|
|
|
2013-02-13 19:01:51 -05:00
|
|
|
native.xpath(form_elements_xpath).map do |field|
|
2011-04-05 11:42:12 -04:00
|
|
|
case field.name
|
2018-05-16 15:47:08 -04:00
|
|
|
when 'input' then add_input_param(field, params)
|
|
|
|
when 'select' then add_select_param(field, params)
|
|
|
|
when 'textarea' then add_textarea_param(field, params)
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|
|
|
|
end
|
2018-07-10 17:18:39 -04:00
|
|
|
merge_param!(params, button[:name], button[:value] || '') if button[:name]
|
2015-10-28 16:26:45 -04:00
|
|
|
|
|
|
|
params.to_params_hash
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def submit(button)
|
2018-05-16 15:47:08 -04:00
|
|
|
action = button&.[]('formaction') || native['action']
|
|
|
|
method = button&.[]('formmethod') || request_method
|
2015-11-08 19:06:15 -05:00
|
|
|
driver.submit(method, action.to_s, params(button))
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def multipart?
|
2018-07-10 17:18:39 -04:00
|
|
|
self[:enctype] == 'multipart/form-data'
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2015-10-28 16:26:45 -04:00
|
|
|
class ParamsHash < Hash
|
|
|
|
def to_params_hash
|
|
|
|
self
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-11-08 19:06:15 -05:00
|
|
|
def request_method
|
2011-04-05 11:42:12 -04:00
|
|
|
self[:method] =~ /post/i ? :post : :get
|
|
|
|
end
|
|
|
|
|
|
|
|
def merge_param!(params, key, value)
|
2018-05-16 15:47:08 -04:00
|
|
|
key = key.to_s
|
2015-10-28 16:26:45 -04:00
|
|
|
if Rack::Utils.respond_to?(:default_query_parser)
|
|
|
|
Rack::Utils.default_query_parser.normalize_params(params, key, value, Rack::Utils.param_depth_limit)
|
|
|
|
else
|
|
|
|
Rack::Utils.normalize_params(params, key, value)
|
|
|
|
end
|
2015-09-29 17:43:48 -04:00
|
|
|
end
|
|
|
|
|
2015-10-28 16:26:45 -04:00
|
|
|
def make_params
|
|
|
|
if Rack::Utils.respond_to?(:default_query_parser)
|
|
|
|
Rack::Utils.default_query_parser.make_params
|
2015-09-29 17:43:48 -04:00
|
|
|
else
|
2015-10-28 16:26:45 -04:00
|
|
|
ParamsHash.new
|
2015-09-29 17:43:48 -04:00
|
|
|
end
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|
2017-11-13 16:04:47 -05:00
|
|
|
|
|
|
|
def add_input_param(field, params)
|
2018-01-09 17:05:50 -05:00
|
|
|
if %w[radio checkbox].include? field['type']
|
2017-11-13 16:04:47 -05:00
|
|
|
if field['checked']
|
2018-01-09 17:05:50 -05:00
|
|
|
node = Capybara::RackTest::Node.new(driver, field)
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], node.value.to_s)
|
2017-11-13 16:04:47 -05:00
|
|
|
end
|
2018-01-09 17:05:50 -05:00
|
|
|
elsif %w[submit image].include? field['type']
|
2018-01-13 16:06:03 -05:00
|
|
|
# TODO: identify the click button here (in document order, rather
|
2017-11-13 16:04:47 -05:00
|
|
|
# than leaving until the end of the params)
|
2018-01-09 17:05:50 -05:00
|
|
|
elsif field['type'] == 'file'
|
2017-11-13 16:04:47 -05:00
|
|
|
if multipart?
|
2018-01-13 16:06:03 -05:00
|
|
|
file = if (value = field['value']).to_s.empty?
|
|
|
|
NilUploadedFile.new
|
|
|
|
else
|
|
|
|
mime_info = MiniMime.lookup_by_filename(value)
|
2018-05-16 15:47:08 -04:00
|
|
|
Rack::Test::UploadedFile.new(value, mime_info&.content_type&.to_s)
|
2018-01-13 16:06:03 -05:00
|
|
|
end
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], file)
|
2017-11-13 16:04:47 -05:00
|
|
|
else
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], File.basename(field['value'].to_s))
|
2017-11-13 16:04:47 -05:00
|
|
|
end
|
|
|
|
else
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], field['value'].to_s)
|
2017-11-13 16:04:47 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_select_param(field, params)
|
2018-05-16 15:47:08 -04:00
|
|
|
if field.has_attribute?('multiple')
|
2018-07-10 17:18:39 -04:00
|
|
|
field.xpath('.//option[@selected]').each do |option|
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], (option['value'] || option.text).to_s)
|
2017-11-13 16:04:47 -05:00
|
|
|
end
|
|
|
|
else
|
2018-01-13 16:06:03 -05:00
|
|
|
option = field.xpath('.//option[@selected]').first || field.xpath('.//option').first
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], (option['value'] || option.text).to_s) if option
|
2017-11-13 16:04:47 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def add_textarea_param(field, params)
|
2018-05-16 15:47:08 -04:00
|
|
|
merge_param!(params, field['name'], field['_capybara_raw_value'].to_s.gsub(/\n/, "\r\n"))
|
2017-11-13 16:04:47 -05:00
|
|
|
end
|
2011-04-05 11:42:12 -04:00
|
|
|
end
|