Emulate click on file input when attaching file using Selenium with Chrome and Firefox

This commit is contained in:
Thomas Walpole 2019-08-16 14:21:20 -07:00
parent 2e052792a5
commit ea6486b328
7 changed files with 40 additions and 5 deletions

View File

@ -288,6 +288,7 @@ module Capybara
execute_script CAPTURE_FILE_ELEMENT_SCRIPT
yield
file_field = evaluate_script 'window._capybara_clicked_file_input'
raise ArgumentError, "Capybara was unable to determine the file input you're attaching to" unless file_field
rescue ::Capybara::NotSupportedByDriverError
warn 'Block mode of `#attach_file` is not supported by the current driver - ignoring.'
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class Capybara::Selenium::Node
module FileInputClickEmulation
private
def visible_file_field?
(attrs(:tagName, :type).map { |val| val&.downcase } == %w[input file]) && visible?
end
def attaching_file?
caller_locations.any? { |cl| cl.base_label == 'attach_file' }
end
def emulate_click
driver.execute_script(<<~JS, self)
arguments[0].dispatchEvent(
new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
}));
JS
end
end
end

View File

@ -1,9 +1,11 @@
# frozen_string_literal: true
require 'capybara/selenium/extensions/html5_drag'
require 'capybara/selenium/extensions/file_input_click_emulation'
class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
include Html5Drag
include FileInputClickEmulation
def set_text(value, clear: nil, **_unused)
super.tap do
@ -34,6 +36,10 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
def click(*)
super
rescue Selenium::WebDriver::Error::InvalidArgumentError
return emulate_click if attaching_file? && visible_file_field?
raise
rescue ::Selenium::WebDriver::Error::ElementClickInterceptedError
raise
rescue ::Selenium::WebDriver::Error::WebDriverError => e

View File

@ -1,12 +1,18 @@
# frozen_string_literal: true
require 'capybara/selenium/extensions/html5_drag'
require 'capybara/selenium/extensions/file_input_click_emulation'
class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
include Html5Drag
include FileInputClickEmulation
def click(keys = [], **options)
super
rescue Selenium::WebDriver::Error::InvalidArgumentError
return emulate_click if attaching_file? && visible_file_field?
raise
rescue ::Selenium::WebDriver::Error::ElementNotInteractableError
if tag_name == 'tr'
warn 'You are attempting to click a table row which has issues in geckodriver/marionette - '\

View File

@ -189,7 +189,7 @@ Capybara::SpecHelper.spec '#attach_file' do
end
context 'with a block', requires: %i[js] do
it 'can upload by clicking the file input' do
it 'can upload by clicking the file input', :focus_ do
@session.attach_file(with_os_path_separators(__FILE__)) do
@session.find(:file_field, 'form[image]').click
end

View File

@ -62,8 +62,6 @@ Capybara::SpecHelper.run_specs TestSessions::SeleniumFirefox, 'selenium', capyba
skip 'Need to figure out testing of file downloading on windows platform' if Gem.win_platform?
when 'Capybara::Session selenium #reset_session! removes ALL cookies'
pending "Geckodriver doesn't provide a way to remove cookies outside the current domain"
when 'Capybara::Session selenium #attach_file with a block can upload by clicking the file input'
pending "Geckodriver doesn't allow clicking on file inputs"
when /drag_to.*HTML5/
pending "Firefox < 62 doesn't support a DataTransfer constuctor" if firefox_lt?(62.0, @session)
end

View File

@ -65,8 +65,6 @@ Capybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVE
when /#accept_confirm should work with nested modals$/
# skip because this is timing based and hence flaky when set to pending
skip 'Broken in FF 63 - https://bugzilla.mozilla.org/show_bug.cgi?id=1487358' if firefox_gte?(63, @session)
when 'Capybara::Session selenium_firefox_remote #attach_file with a block can upload by clicking the file input'
pending "Geckodriver doesn't allow clicking on file inputs"
end
end