Support block mode for attach_file
This commit is contained in:
parent
4395d6f2bb
commit
6c2d0f3c1f
|
@ -231,11 +231,14 @@ module Capybara
|
|||
|
||||
##
|
||||
#
|
||||
# Find a descendant file field on the page and attach a file given its path. The file field can
|
||||
# be found via its name, id or label text. In the case of the file field being hidden for
|
||||
# Find a descendant file field on the page and attach a file given its path. There are two ways to use
|
||||
# `attach_file`, in the first method the file field can be found via its name, id or label text.
|
||||
# In the case of the file field being hidden for
|
||||
# styling reasons the `make_visible` option can be used to temporarily change the CSS of
|
||||
# the file field, attach the file, and then revert the CSS back to original. If no locator is
|
||||
# passed this will match self or a descendant.
|
||||
# The second method, which is currently in beta and may be changed/removed, involves passing a block
|
||||
# which performs whatever actions would trigger the file chooser to appear.
|
||||
#
|
||||
# # will attach file to a descendant file input element that has a name, id, or label_text matching 'My File'
|
||||
# page.attach_file('My File', '/path/to/file.png')
|
||||
|
@ -243,6 +246,11 @@ module Capybara
|
|||
# # will attach file to el if it's a file input element
|
||||
# el.attach_file('/path/to/file.png')
|
||||
#
|
||||
# # will attach file to whatever file input is triggered by the block
|
||||
# page.attach_file('/path/to/file.png') do
|
||||
# page.find('#upload_button').click
|
||||
# end
|
||||
#
|
||||
# @overload attach_file([locator], paths, **options)
|
||||
# @macro waiting_behavior
|
||||
#
|
||||
|
@ -256,19 +264,33 @@ module Capybara
|
|||
# @option options [String] name Match fields that match the name attribute
|
||||
# @option options [String, Array<String>, Regexp] class Match fields that match the class(es) provided
|
||||
# @option options [true, Hash] make_visible A Hash of CSS styles to change before attempting to attach the file, if `true` { opacity: 1, display: 'block', visibility: 'visible' } is used (may not be supported by all drivers)
|
||||
#
|
||||
# @return [Capybara::Node::Element] The file field element
|
||||
# @overload attach_file(paths, &blk)
|
||||
# @param [String, Array<String>] paths The path(s) of the file(s) that will be attached
|
||||
# @yield Block whose actions will trigger the system file chooser to be shown
|
||||
# @return [Capybara::Node::Element] The file field element
|
||||
def attach_file(locator = nil, paths, make_visible: nil, **options) # rubocop:disable Style/OptionalArguments
|
||||
raise ArgumentError, '``#attach_file` does not support passing both a locator and a block' if locator && block_given?
|
||||
|
||||
Array(paths).each do |path|
|
||||
raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
|
||||
end
|
||||
options[:allow_self] = true if locator.nil?
|
||||
|
||||
if block_given?
|
||||
begin
|
||||
execute_script CAPTURE_FILE_ELEMENT_SCRIPT
|
||||
yield
|
||||
file_field = evaluate_script 'window._capybara_clicked_file_input'
|
||||
rescue ::Capybara::NotSupportedByDriverError
|
||||
warn 'Block mode of `#attach_file` is not supported by the current driver - ignoring.'
|
||||
end
|
||||
end
|
||||
# Allow user to update the CSS style of the file input since they are so often hidden on a page
|
||||
if make_visible
|
||||
ff = find(:file_field, locator, options.merge(visible: :all))
|
||||
ff = file_field || find(:file_field, locator, options.merge(visible: :all))
|
||||
while_visible(ff, make_visible) { |el| el.set(paths) }
|
||||
else
|
||||
find(:file_field, locator, options).set(paths)
|
||||
(file_field || find(:file_field, locator, options)).set(paths)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -369,6 +391,16 @@ module Capybara
|
|||
filter(function(el){ return !el.disabled }).
|
||||
map(function(el){ return { "value": el.value, "label": el.label} })
|
||||
JS
|
||||
|
||||
CAPTURE_FILE_ELEMENT_SCRIPT = <<~'JS'
|
||||
document.addEventListener('click', function(e){
|
||||
console.log(e);
|
||||
if ((e.target.nodeName == 'INPUT') && (e.target['type'] == 'file')) {
|
||||
window._capybara_clicked_file_input = e.target;
|
||||
e.preventDefault();
|
||||
}
|
||||
})
|
||||
JS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -181,6 +181,16 @@ Capybara::SpecHelper.spec '#attach_file' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with a block', requires: %i[js] do
|
||||
it 'can upload by clicking the label' do
|
||||
@session.attach_file(with_os_path_separators(__FILE__)) do
|
||||
@session.find(:label, 'Hidden Image').click
|
||||
end
|
||||
@session.click_button('awesome')
|
||||
expect(extract_results(@session)['hidden_image']).to end_with(File.basename(__FILE__))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_os_path_separators(path)
|
||||
|
|
|
@ -94,6 +94,11 @@
|
|||
<input type="file" name="form[image]" id="form_image"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label for="form_hidden_image">Hidden Image</label>
|
||||
<input type="file" name="form[hidden_image]" id="form_hidden_image" style="display: none"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="hidden" name="form[token]" value="12345" id="form_token"/>
|
||||
</p>
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
|
||||
<p>
|
||||
<input type="file" id="hidden_file" style="opacity:0; display: none;">
|
||||
<label for="hidden_file">Label for hidden file input</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
Loading…
Reference in New Issue