mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Workaround geckodriver/firefox deficient send_keys implementation as much as possible
This commit is contained in:
parent
6711aed299
commit
3e5f82bb23
5 changed files with 47 additions and 14 deletions
|
@ -47,7 +47,6 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
||||||
# Array => an array of keys to send before the value being set, e.g. [[:command, 'a'], :backspace]
|
# Array => an array of keys to send before the value being set, e.g. [[:command, 'a'], :backspace]
|
||||||
def set(value, **options)
|
def set(value, **options)
|
||||||
raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" if value.is_a?(Array) && !multiple?
|
raise ArgumentError, "Value cannot be an Array when 'multiple' attribute is not present. Not a #{value.class}" if value.is_a?(Array) && !multiple?
|
||||||
|
|
||||||
case tag_name
|
case tag_name
|
||||||
when 'input'
|
when 'input'
|
||||||
case self[:type]
|
case self[:type]
|
||||||
|
@ -212,17 +211,17 @@ private
|
||||||
elsif clear == :backspace
|
elsif clear == :backspace
|
||||||
# Clear field by sending the correct number of backspace keys.
|
# Clear field by sending the correct number of backspace keys.
|
||||||
backspaces = [:backspace] * self.value.to_s.length
|
backspaces = [:backspace] * self.value.to_s.length
|
||||||
native.send_keys(*([:end] + backspaces + [value.to_s]))
|
send_keys(*([:end] + backspaces + [value.to_s]))
|
||||||
elsif clear == :none
|
elsif clear == :none
|
||||||
native.send_keys(value.to_s)
|
send_keys(value.to_s)
|
||||||
elsif clear.is_a? Array
|
elsif clear.is_a? Array
|
||||||
native.send_keys(*clear, value.to_s)
|
send_keys(*clear, value.to_s)
|
||||||
else
|
else
|
||||||
# Clear field by JavaScript assignment of the value property.
|
# Clear field by JavaScript assignment of the value property.
|
||||||
# Script can change a readonly element which user input cannot, so
|
# Script can change a readonly element which user input cannot, so
|
||||||
# don't execute if readonly.
|
# don't execute if readonly.
|
||||||
driver.execute_script "arguments[0].value = ''", self
|
driver.execute_script "arguments[0].value = ''", self
|
||||||
native.send_keys(value.to_s)
|
send_keys(value.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,51 @@ class Capybara::Selenium::MarionetteNode < Capybara::Selenium::Node
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_keys(*args)
|
||||||
|
# https://github.com/mozilla/geckodriver/issues/846
|
||||||
|
return super(*args.map { |arg| arg == :space ? ' ' : arg }) if args.none? { |s| s.is_a? Array }
|
||||||
|
|
||||||
|
native.click
|
||||||
|
actions = driver.browser.action
|
||||||
|
args.each do |keys|
|
||||||
|
_send_keys(keys, actions)
|
||||||
|
end
|
||||||
|
actions.perform
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def _send_keys(keys, actions, down_keys = nil)
|
||||||
|
case keys
|
||||||
|
when String
|
||||||
|
keys = keys.upcase if down_keys&.include?(:shift) # https://bugzilla.mozilla.org/show_bug.cgi?id=1405370
|
||||||
|
actions.send_keys(keys)
|
||||||
|
when :space
|
||||||
|
actions.send_keys(' ') # https://github.com/mozilla/geckodriver/issues/846
|
||||||
|
when :control, :left_control, :right_control,
|
||||||
|
:alt, :left_alt, :right_alt,
|
||||||
|
:shift, :left_shift, :right_shift,
|
||||||
|
:meta, :left_meta, :right_meta,
|
||||||
|
:command
|
||||||
|
if down_keys.nil?
|
||||||
|
actions.send_keys(keys)
|
||||||
|
else
|
||||||
|
down_keys << keys
|
||||||
|
actions.key_down(keys)
|
||||||
|
end
|
||||||
|
when Symbol
|
||||||
|
actions.send_keys(keys)
|
||||||
|
when Array
|
||||||
|
local_down_keys = []
|
||||||
|
keys.each do |sub_keys|
|
||||||
|
_send_keys(sub_keys, actions, local_down_keys)
|
||||||
|
end
|
||||||
|
local_down_keys.each { |key| actions.key_up(key) }
|
||||||
|
else
|
||||||
|
raise ArgumentError, 'Unknown keys type'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def bridge
|
def bridge
|
||||||
driver.browser.send(:bridge)
|
driver.browser.send(:bridge)
|
||||||
end
|
end
|
||||||
|
|
|
@ -60,10 +60,6 @@ skipped_tests << :windows if ENV['TRAVIS'] && (ENV['SKIP_WINDOW'] || ENV['HEADLE
|
||||||
|
|
||||||
Capybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
|
Capybara::SpecHelper.run_specs TestSessions::RemoteFirefox, FIREFOX_REMOTE_DRIVER.to_s, capybara_skip: skipped_tests do |example|
|
||||||
case example.metadata[:full_description]
|
case example.metadata[:full_description]
|
||||||
when 'Capybara::Session selenium_firefox_remote node #send_keys should generate key events',
|
|
||||||
'Capybara::Session selenium_firefox_remote node #send_keys should allow for multiple simultaneous keys',
|
|
||||||
'Capybara::Session selenium_firefox_remote node #send_keys should send special characters'
|
|
||||||
pending "selenium-webdriver/geckodriver doesn't support complex sets of characters"
|
|
||||||
when 'Capybara::Session selenium_firefox_remote node #click should allow multiple modifiers'
|
when 'Capybara::Session selenium_firefox_remote node #click should allow multiple modifiers'
|
||||||
pending "Firefox doesn't generate an event for shift+control+click" if marionette_gte?(62, @session)
|
pending "Firefox doesn't generate an event for shift+control+click" if marionette_gte?(62, @session)
|
||||||
when /^Capybara::Session selenium node #double_click/
|
when /^Capybara::Session selenium node #double_click/
|
||||||
|
|
|
@ -50,10 +50,6 @@ $stdout.puts `#{Selenium::WebDriver::Firefox.driver_path} --version` if ENV['CI'
|
||||||
|
|
||||||
Capybara::SpecHelper.run_specs TestSessions::SeleniumMarionette, 'selenium', capybara_skip: skipped_tests do |example|
|
Capybara::SpecHelper.run_specs TestSessions::SeleniumMarionette, 'selenium', capybara_skip: skipped_tests do |example|
|
||||||
case example.metadata[:full_description]
|
case example.metadata[:full_description]
|
||||||
when 'Capybara::Session selenium node #send_keys should generate key events',
|
|
||||||
'Capybara::Session selenium node #send_keys should allow for multiple simultaneous keys',
|
|
||||||
'Capybara::Session selenium node #send_keys should send special characters'
|
|
||||||
pending "selenium-webdriver/geckodriver doesn't support complex sets of characters"
|
|
||||||
when 'Capybara::Session selenium node #click should allow multiple modifiers'
|
when 'Capybara::Session selenium node #click should allow multiple modifiers'
|
||||||
pending "Firefox doesn't generate an event for shift+control+click" if marionette_gte?(62, @session)
|
pending "Firefox doesn't generate an event for shift+control+click" if marionette_gte?(62, @session)
|
||||||
when /^Capybara::Session selenium node #double_click/
|
when /^Capybara::Session selenium node #double_click/
|
||||||
|
|
|
@ -185,7 +185,6 @@ RSpec.shared_examples 'Capybara::Session' do |session, mode|
|
||||||
|
|
||||||
context '#fill_in with { clear: Array } fill_options' do
|
context '#fill_in with { clear: Array } fill_options' do
|
||||||
it 'should pass the array through to the element' do
|
it 'should pass the array through to the element' do
|
||||||
pending "selenium-webdriver/geckodriver doesn't support complex sets of characters" if marionette?(session)
|
|
||||||
# this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
|
# this is mainly for use with [[:control, 'a'], :backspace] - however since that is platform dependant I'm testing with something less useful
|
||||||
session.visit('/form')
|
session.visit('/form')
|
||||||
session.fill_in('form_first_name',
|
session.fill_in('form_first_name',
|
||||||
|
|
Loading…
Reference in a new issue