mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
minor refactor
This commit is contained in:
parent
952d373026
commit
a6e289f6cc
3 changed files with 47 additions and 43 deletions
|
@ -174,41 +174,12 @@ module Capybara
|
|||
#
|
||||
# @return [Capybara::Node::Element] The option element selected
|
||||
def select(value = nil, from: nil, **options)
|
||||
scope = if from
|
||||
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
||||
begin
|
||||
find(:select, from, options)
|
||||
rescue Capybara::ElementNotFound => select_error
|
||||
raise if %i[selected with_selected multiple].any? { |option| options.key?(option) }
|
||||
begin
|
||||
find(:datalist_input, from, options)
|
||||
rescue Capybara::ElementNotFound => dlinput_error
|
||||
raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
self
|
||||
end
|
||||
el = from ? find_select_or_datalist_input(from, options) : self
|
||||
|
||||
if scope.respond_to?(:tag_name) && scope.tag_name == "input"
|
||||
begin
|
||||
# TODO: this is a more efficient but won't work with non-JS drivers
|
||||
# datalist_options = session.evaluate_script('Array.prototype.slice.call((arguments[0].list||{}).options || []).filter(function(el){ return !el.disabled }).map(function(el){ return { "value": el.value, "label": el.label} })', scope)
|
||||
datalist_options = session.evaluate_script(DATALIST_OPTIONS_SCRIPT, scope)
|
||||
if (option = datalist_options.find { |o| o['value'] == value || o['label'] == value })
|
||||
scope.set(option["value"])
|
||||
if el.respond_to?(:tag_name) && (el.tag_name == "input")
|
||||
select_datalist_option(el, value)
|
||||
else
|
||||
raise ::Capybara::ElementNotFound, "Unable to find datalist option \"#{value}\""
|
||||
end
|
||||
rescue ::Capybara::NotSupportedByDriverError
|
||||
# Implement for drivers that don't support JS
|
||||
datalist = find(:xpath, XPath.descendant(:datalist)[XPath.attr(:id) == scope[:list]], visible: false)
|
||||
option = datalist.find(:datalist_option, value, disabled: false)
|
||||
scope.set(option.value)
|
||||
end
|
||||
else
|
||||
scope.find(:option, value, options).select_option
|
||||
el.find(:option, value, options).select_option
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -267,6 +238,35 @@ module Capybara
|
|||
|
||||
private
|
||||
|
||||
def find_select_or_datalist_input(from, options)
|
||||
synchronize(Capybara::Queries::BaseQuery.wait(options, session_options.default_max_wait_time)) do
|
||||
begin
|
||||
find(:select, from, options)
|
||||
rescue Capybara::ElementNotFound => select_error
|
||||
raise if %i[selected with_selected multiple].any? { |option| options.key?(option) }
|
||||
begin
|
||||
find(:datalist_input, from, options)
|
||||
rescue Capybara::ElementNotFound => dlinput_error
|
||||
raise Capybara::ElementNotFound, "#{select_error.message} and #{dlinput_error.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def select_datalist_option(input, value)
|
||||
datalist_options = session.evaluate_script(DATALIST_OPTIONS_SCRIPT, input)
|
||||
if (option = datalist_options.find { |o| o['value'] == value || o['label'] == value })
|
||||
input.set(option["value"])
|
||||
else
|
||||
raise ::Capybara::ElementNotFound, "Unable to find datalist option \"#{value}\""
|
||||
end
|
||||
rescue ::Capybara::NotSupportedByDriverError
|
||||
# Implement for drivers that don't support JS
|
||||
datalist = find(:xpath, XPath.descendant(:datalist)[XPath.attr(:id) == input[:list]], visible: false)
|
||||
option = datalist.find(:datalist_option, value, disabled: false)
|
||||
input.set(option.value)
|
||||
end
|
||||
|
||||
def while_visible(element, visible_css)
|
||||
visible_css = { opacity: 1, display: 'block', visibility: 'visible' } if visible_css == true
|
||||
_update_style(element, visible_css)
|
||||
|
|
|
@ -245,7 +245,7 @@ module Capybara
|
|||
minimum_specified = options_include_minimum?(options)
|
||||
options = { minimum: 1 }.merge(options) unless minimum_specified
|
||||
options[:session_options] = session_options
|
||||
query = Capybara::Queries::SelectorQuery.new(*args.push(options), &optional_filter_block)
|
||||
query = Capybara::Queries::SelectorQuery.new(*args, options, &optional_filter_block)
|
||||
result = nil
|
||||
begin
|
||||
synchronize(query.wait) do
|
||||
|
@ -298,11 +298,11 @@ module Capybara
|
|||
end
|
||||
|
||||
def ambiguous?(query, result)
|
||||
((query.match == :one) || (query.match == :smart)) && (result.size > 1)
|
||||
%i[one smart].include?(query.match) && (result.size > 1)
|
||||
end
|
||||
|
||||
def prefer_exact?(query)
|
||||
(query.match == :smart) || (query.match == :prefer_exact)
|
||||
%i[smart prefer_exact].include?(query.match)
|
||||
end
|
||||
|
||||
def options_include_minimum?(opts)
|
||||
|
|
|
@ -93,11 +93,7 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
|
|||
rescue StandardError => e
|
||||
if e.is_a?(::Selenium::WebDriver::Error::ElementClickInterceptedError) ||
|
||||
e.message =~ /Other element would receive the click/
|
||||
begin
|
||||
driver.execute_script("arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'})", self)
|
||||
rescue StandardError # rubocop:disable Lint/HandleExceptions
|
||||
# Swallow error if scrollIntoView with options isn't supported
|
||||
end
|
||||
scroll_to_center
|
||||
end
|
||||
raise e
|
||||
end
|
||||
|
@ -230,6 +226,11 @@ private
|
|||
def scroll_if_needed
|
||||
yield
|
||||
rescue ::Selenium::WebDriver::Error::MoveTargetOutOfBoundsError
|
||||
scroll_to_center
|
||||
yield
|
||||
end
|
||||
|
||||
def scroll_to_center
|
||||
script = <<-'JS'
|
||||
try {
|
||||
arguments[0].scrollIntoView({behavior: 'instant', block: 'center', inline: 'center'});
|
||||
|
@ -237,8 +238,11 @@ private
|
|||
arguments[0].scrollIntoView(true);
|
||||
}
|
||||
JS
|
||||
begin
|
||||
driver.execute_script(script, self)
|
||||
yield
|
||||
rescue StandardError # rubocop:disable Lint/HandleExceptions
|
||||
# Swallow error if scrollIntoView with options isn't supported
|
||||
end
|
||||
end
|
||||
|
||||
def set_date(value) # rubocop:disable Naming/AccessorMethodName
|
||||
|
|
Loading…
Reference in a new issue