mirror of
https://github.com/teamcapybara/capybara.git
synced 2022-11-09 12:08:07 -05:00
Add #first, and use it in preference to all(*args).first.
This provides a ~10% speed improvement on selenium specs.
This commit is contained in:
parent
c7de62d88a
commit
74aa0ca844
2 changed files with 65 additions and 45 deletions
|
@ -25,7 +25,7 @@ module Capybara
|
|||
#
|
||||
def find(*args)
|
||||
begin
|
||||
node = wait_conditionally_until { all(*args).first }
|
||||
node = wait_conditionally_until { first(*args) }
|
||||
rescue TimeoutError
|
||||
end
|
||||
unless node
|
||||
|
@ -115,46 +115,39 @@ module Capybara
|
|||
# @return [Capybara::Element] The found elements
|
||||
#
|
||||
def all(*args)
|
||||
options = if args.last.is_a?(Hash) then args.pop else {} end
|
||||
options = extract_normalized_options(args)
|
||||
|
||||
results = Capybara::Selector.normalize(*args).map do |path|
|
||||
find_in_base(path)
|
||||
end.flatten
|
||||
Capybara::Selector.normalize(*args).
|
||||
map { |path| find_in_base(path) }.flatten.
|
||||
select { |node| matches_options(node, options) }.
|
||||
map { |node| convert_element(node) }
|
||||
end
|
||||
|
||||
if text = options[:text]
|
||||
text = Regexp.escape(text) unless text.kind_of?(Regexp)
|
||||
##
|
||||
#
|
||||
# Find the first element on the page matching the given selector
|
||||
# and options, or nil if no element matches.
|
||||
#
|
||||
# When only the first matching element is needed, this method can
|
||||
# be faster than all(*args).first.
|
||||
#
|
||||
# @param [:css, :xpath, String] kind_or_locator Either the kind of selector or the selector itself
|
||||
# @param [String] locator The selector
|
||||
# @param [Hash{Symbol => Object}] options Additional options; see {all}
|
||||
# @return Capybara::Element The found element
|
||||
#
|
||||
def first(*args)
|
||||
options = extract_normalized_options(args)
|
||||
|
||||
results = results.select { |node| node.text.match(text) }
|
||||
Capybara::Selector.normalize(*args).each do |path|
|
||||
find_in_base(path).each do |node|
|
||||
if matches_options(node, options)
|
||||
return convert_element(node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if value = options[:with]
|
||||
results = results.select { |node| node.value == value }
|
||||
end
|
||||
|
||||
if options[:checked]
|
||||
results = results.select { |node| node.checked? }
|
||||
end
|
||||
|
||||
if options[:unchecked]
|
||||
results = results.reject { |node| node.checked? }
|
||||
end
|
||||
|
||||
if selected = options[:selected]
|
||||
selected = [selected].flatten
|
||||
results = results.select { |node| has_selected_options?(node, selected) }
|
||||
end
|
||||
|
||||
ignore_hidden = if options.has_key?(:visible)
|
||||
options[:visible]
|
||||
else
|
||||
Capybara.ignore_hidden_elements
|
||||
end
|
||||
|
||||
if ignore_hidden
|
||||
results = results.select { |node| node.visible? }
|
||||
end
|
||||
|
||||
convert_elements(results)
|
||||
nil
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -163,19 +156,46 @@ module Capybara
|
|||
base.find(xpath)
|
||||
end
|
||||
|
||||
def has_selected_options?(node, expected)
|
||||
actual = node.find('.//option').select { |option| option.selected? }.map { |option| option.text }
|
||||
(expected - actual).empty?
|
||||
end
|
||||
|
||||
def convert_elements(elements)
|
||||
elements.map { |element| Capybara::Node::Element.new(session, element) }
|
||||
def convert_element(element)
|
||||
Capybara::Node::Element.new(session, element)
|
||||
end
|
||||
|
||||
def wait_conditionally_until
|
||||
if wait? then session.wait_until { yield } else yield end
|
||||
end
|
||||
|
||||
def extract_normalized_options(args)
|
||||
options = if args.last.is_a?(Hash) then args.pop.dup else {} end
|
||||
|
||||
if text = options[:text]
|
||||
options[:text] = Regexp.escape(text) unless text.kind_of?(Regexp)
|
||||
end
|
||||
|
||||
if !options.has_key?(:visible)
|
||||
options[:visible] = Capybara.ignore_hidden_elements
|
||||
end
|
||||
|
||||
if selected = options[:selected]
|
||||
options[:selected] = [selected].flatten
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def matches_options(node, options)
|
||||
return false if options[:text] and not node.text.match(options[:text])
|
||||
return false if options[:visible] and not node.visible?
|
||||
return false if options[:with] and not node.value == options[:with]
|
||||
return false if options[:checked] and not node.checked?
|
||||
return false if options[:unchecked] and node.checked?
|
||||
return false if options[:selected] and not has_selected_options?(node, options[:selected])
|
||||
true
|
||||
end
|
||||
|
||||
def has_selected_options?(node, expected)
|
||||
actual = node.find('.//option').select { |option| option.selected? }.map { |option| option.text }
|
||||
(expected - actual).empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -104,8 +104,8 @@ module Capybara
|
|||
native.xpath(xpath).map { |node| self.class.new(node) }
|
||||
end
|
||||
|
||||
def convert_elements(elements)
|
||||
elements
|
||||
def convert_element(element)
|
||||
element
|
||||
end
|
||||
|
||||
def wait?
|
||||
|
|
Loading…
Reference in a new issue