Optimize wirecalls in selenium driver
This commit is contained in:
parent
32297d027c
commit
72ec06b0c4
|
@ -126,7 +126,6 @@ module Capybara
|
||||||
#
|
#
|
||||||
# @return [Capybara::Node::Element] The element
|
# @return [Capybara::Node::Element] The element
|
||||||
def select_option(wait: nil)
|
def select_option(wait: nil)
|
||||||
warn "Attempt to select disabled option: #{value || text}" if disabled?
|
|
||||||
synchronize(wait) { base.select_option }
|
synchronize(wait) { base.select_option }
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
@ -276,7 +275,8 @@ module Capybara
|
||||||
# @return [String] The tag name of the element
|
# @return [String] The tag name of the element
|
||||||
#
|
#
|
||||||
def tag_name
|
def tag_name
|
||||||
synchronize { base.tag_name }
|
# Element type is immutable so cache it
|
||||||
|
@tag_name ||= synchronize { base.tag_name }
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -56,10 +56,12 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
||||||
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?
|
||||||
|
|
||||||
tag_name, type = attrs(:tagName, :type)
|
tag_name, type = attrs(:tagName, :type).map { |val| val&.downcase }
|
||||||
case tag_name.downcase
|
@tag_name ||= tag_name
|
||||||
|
|
||||||
|
case tag_name
|
||||||
when 'input'
|
when 'input'
|
||||||
case type.downcase
|
case type
|
||||||
when 'radio'
|
when 'radio'
|
||||||
click
|
click
|
||||||
when 'checkbox'
|
when 'checkbox'
|
||||||
|
@ -78,7 +80,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
||||||
when 'textarea'
|
when 'textarea'
|
||||||
set_text(value, options)
|
set_text(value, options)
|
||||||
else
|
else
|
||||||
set_content_editable(value) if content_editable?
|
set_content_editable(value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -136,7 +138,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_name
|
def tag_name
|
||||||
native.tag_name.downcase
|
@tag_name ||= native.tag_name.downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
def visible?; boolean_attr(native.displayed?); end
|
def visible?; boolean_attr(native.displayed?); end
|
||||||
|
@ -291,20 +293,24 @@ private
|
||||||
# Ensure we are focused on the element
|
# Ensure we are focused on the element
|
||||||
click
|
click
|
||||||
|
|
||||||
driver.execute_script <<-JS, self
|
editable = driver.execute_script <<-JS, self
|
||||||
var range = document.createRange();
|
if (arguments[0].isContentEditable) {
|
||||||
var sel = window.getSelection();
|
var range = document.createRange();
|
||||||
arguments[0].focus();
|
var sel = window.getSelection();
|
||||||
range.selectNodeContents(arguments[0]);
|
arguments[0].focus();
|
||||||
sel.removeAllRanges();
|
range.selectNodeContents(arguments[0]);
|
||||||
sel.addRange(range);
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(range);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
JS
|
JS
|
||||||
|
|
||||||
# The action api has a speed problem but both chrome and firefox 58 raise errors
|
# The action api has a speed problem but both chrome and firefox 58 raise errors
|
||||||
# if we use the faster direct send_keys. For now just send_keys to the element
|
# if we use the faster direct send_keys. For now just send_keys to the element
|
||||||
# we've already focused.
|
# we've already focused.
|
||||||
# native.send_keys(value.to_s)
|
# native.send_keys(value.to_s)
|
||||||
browser_action.send_keys(value.to_s).perform
|
browser_action.send_keys(value.to_s).perform if editable
|
||||||
end
|
end
|
||||||
|
|
||||||
def action_with_modifiers(click_options)
|
def action_with_modifiers(click_options)
|
||||||
|
|
|
@ -39,6 +39,14 @@ class Capybara::Selenium::ChromeNode < Capybara::Selenium::Node
|
||||||
driver.evaluate_script("arguments[0].matches(':disabled, select:disabled *')", self)
|
driver.evaluate_script("arguments[0].matches(':disabled, select:disabled *')", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def select_option
|
||||||
|
# To optimize to only one check and then click
|
||||||
|
selected_or_disabled = driver.evaluate_script(<<~JS, self)
|
||||||
|
arguments[0].matches(':disabled, select:disabled *, :checked')
|
||||||
|
JS
|
||||||
|
click unless selected_or_disabled
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def file_errors
|
def file_errors
|
||||||
|
|
|
@ -55,6 +55,14 @@ class Capybara::Selenium::FirefoxNode < Capybara::Selenium::Node
|
||||||
scroll_if_needed { browser_action.move_to(native, 0, 0).move_to(native).perform }
|
scroll_if_needed { browser_action.move_to(native, 0, 0).move_to(native).perform }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def select_option
|
||||||
|
# To optimize to only one check and then click
|
||||||
|
selected_or_disabled = driver.evaluate_script(<<~JS, self)
|
||||||
|
arguments[0].matches(':disabled, select:disabled *, :checked')
|
||||||
|
JS
|
||||||
|
click unless selected_or_disabled
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def click_with_options(click_options)
|
def click_with_options(click_options)
|
||||||
|
|
|
@ -19,8 +19,12 @@ class Capybara::Selenium::SafariNode < Capybara::Selenium::Node
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_option
|
def select_option
|
||||||
driver.execute_script("arguments[0].closest('select').scrollIntoView()", self)
|
# To optimize to only one check and then click
|
||||||
super
|
selected_or_disabled = driver.execute_script(<<~JS, self)
|
||||||
|
arguments[0].closest('select').scrollIntoView();
|
||||||
|
return arguments[0].matches(':disabled, select:disabled *, :checked');
|
||||||
|
JS
|
||||||
|
click unless selected_or_disabled
|
||||||
end
|
end
|
||||||
|
|
||||||
def unselect_option
|
def unselect_option
|
||||||
|
|
|
@ -141,11 +141,6 @@ Capybara::SpecHelper.spec '#select' do
|
||||||
@session.select('Other', from: 'form_title')
|
@session.select('Other', from: 'form_title')
|
||||||
expect(@session.find_field('form_title').value).not_to eq 'Other'
|
expect(@session.find_field('form_title').value).not_to eq 'Other'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should warn' do
|
|
||||||
expect { @session.select('Other', from: 'form_title') }.to \
|
|
||||||
output(/^Attempt to select disabled option: Other/).to_stderr
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with multiple select' do
|
context 'with multiple select' do
|
||||||
|
|
Loading…
Reference in New Issue