From 78aae503fc68e3fb22dc21838aa8182894262495 Mon Sep 17 00:00:00 2001 From: Thomas Walpole Date: Mon, 25 Jun 2018 17:27:36 -0700 Subject: [PATCH] Specialize Chrome driver for remote multiple file upload being unsupported --- .../driver_specializations/chrome_driver.rb | 8 ++++++++ lib/capybara/selenium/nodes/chrome_node.rb | 18 ++++++++++++++++++ lib/capybara/selenium/nodes/marionette_node.rb | 5 +++-- lib/capybara/spec/session/attach_file_spec.rb | 7 +++---- spec/selenium_spec_chrome_remote.rb | 9 +++++++++ spec/shared_selenium_session.rb | 1 - 6 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 lib/capybara/selenium/nodes/chrome_node.rb diff --git a/lib/capybara/selenium/driver_specializations/chrome_driver.rb b/lib/capybara/selenium/driver_specializations/chrome_driver.rb index 667d8045..12ebd084 100644 --- a/lib/capybara/selenium/driver_specializations/chrome_driver.rb +++ b/lib/capybara/selenium/driver_specializations/chrome_driver.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'capybara/selenium/nodes/chrome_node' + module Capybara::Selenium::Driver::ChromeDriver def fullscreen_window(handle) within_given_window(handle) do @@ -32,4 +34,10 @@ module Capybara::Selenium::Driver::ChromeDriver window_handles.slice(1..-1).each { |win| close_window(win) } super end + +private + + def build_node(native_node) + ::Capybara::Selenium::ChromeNode.new(self, native_node) + end end diff --git a/lib/capybara/selenium/nodes/chrome_node.rb b/lib/capybara/selenium/nodes/chrome_node.rb new file mode 100644 index 00000000..e099e8f6 --- /dev/null +++ b/lib/capybara/selenium/nodes/chrome_node.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node + def set_file(value) # rubocop:disable Naming/AccessorMethodName + super(value) + rescue ::Selenium::WebDriver::Error::ExpectedError => e + if e.message =~ /File not found : .+\n.+/m + raise ArgumentError, "Selenium with remote Chrome doesn't currently support multiple file upload" + end + raise + end + +private + + def bridge + driver.browser.send(:bridge) + end +end diff --git a/lib/capybara/selenium/nodes/marionette_node.rb b/lib/capybara/selenium/nodes/marionette_node.rb index f726cceb..38d959f3 100644 --- a/lib/capybara/selenium/nodes/marionette_node.rb +++ b/lib/capybara/selenium/nodes/marionette_node.rb @@ -28,7 +28,7 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node native.clear Array(path_names).each do |path| unless driver.browser.respond_to?(:upload) - if (fd = bridge.file_detector) + if (fd = bridge.file_detector) local_file = fd.call([path]) path = upload(local_file) if local_file end @@ -38,6 +38,7 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node end private + def bridge driver.browser.send(:bridge) end @@ -47,7 +48,7 @@ private raise Error::WebDriverError, "you may only upload files: #{local_file.inspect}" end - result = bridge.http.call(:post, "session/#{bridge.session_id}/file", {file: Selenium::WebDriver::Zipper.zip_file(local_file)}) + result = bridge.http.call(:post, "session/#{bridge.session_id}/file", file: Selenium::WebDriver::Zipper.zip_file(local_file)) result['value'] end end diff --git a/lib/capybara/spec/session/attach_file_spec.rb b/lib/capybara/spec/session/attach_file_spec.rb index 91ffe7be..289c681b 100644 --- a/lib/capybara/spec/session/attach_file_spec.rb +++ b/lib/capybara/spec/session/attach_file_spec.rb @@ -88,12 +88,11 @@ Capybara::SpecHelper.spec "#attach_file" do it "should not append files to already attached" do @session.attach_file "Multiple Documents", with_os_path_separators(@test_file_path) - @session.attach_file("Multiple Documents", - [@test_file_path, @another_test_file_path].map { |f| with_os_path_separators(f) }) + @session.attach_file "Multiple Documents", with_os_path_separators(@another_test_file_path) @session.click_button('Upload Multiple') - expect(@session.body).to include("2 | ") # number of files - expect(@session.body).to include(File.read(@test_file_path)) + expect(@session.body).to include("1 | ") # number of files expect(@session.body).to include(File.read(@another_test_file_path)) + expect(@session.body).not_to include(File.read(@test_file_path)) end end diff --git a/spec/selenium_spec_chrome_remote.rb b/spec/selenium_spec_chrome_remote.rb index 770c4d90..c3c4210f 100644 --- a/spec/selenium_spec_chrome_remote.rb +++ b/spec/selenium_spec_chrome_remote.rb @@ -49,6 +49,15 @@ skipped_tests = %i[response_headers status_code trigger download] # skip window tests when headless for now - closing a window not supported by chromedriver/chrome skipped_tests << :windows if ENV['TRAVIS'] && (ENV['SKIP_WINDOW'] || ENV['HEADLESS']) +RSpec.configure do |config| + config.define_derived_metadata do |metadata| + case metadata[:full_description] + when /^Capybara::Session selenium_chrome_remote #attach_file with multipart form should not break when using HTML5 multiple file input uploading multiple files$/ + metadata[:pending] = "Selenium with Remote Chrome doesn't support multiple file upload" + end + end +end + Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests RSpec.describe "Capybara::Session with remote Chrome" do diff --git a/spec/shared_selenium_session.rb b/spec/shared_selenium_session.rb index aefdfd1d..094401b7 100644 --- a/spec/shared_selenium_session.rb +++ b/spec/shared_selenium_session.rb @@ -325,5 +325,4 @@ RSpec.shared_examples "Capybara::Session" do |session, mode| def with_os_path_separators(path) Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s end - end