module Unobtainium::MultiFind::DriverModule
Driver module implementing multi find functionality.
Constants
- DEFAULT_OPTIONS
Default options. This hash is also used to detect if any of the Hashes passed to
multifind
is an options Hash; it is considered one if it contains any of the keys specified here.
Attributes
Current options for multifind
Public Class Methods
Returns true if the implementation has `#find_element`, false otherwise.
# File lib/unobtainium-multifind/multifind.rb, line 49 def matches?(impl) return impl.respond_to?(:find_element) end
Public Instance Methods
Find multiple elements. Each argument is a Hash of selector options that are passed to options. If one argument contains keys from the DEFAULT_OPTIONS
Hash, it is instead treated as an options Hash for the multifind
method. @return Array of found elements or nil entries if no matching element
was found.
# File lib/unobtainium-multifind/multifind.rb, line 66 def multifind(*args) # Parse options options, selectors = multifind_parse_options(*args) # Now find elements results = [] selectors.each do |selector| begin results << send(options[:find_method], selector) rescue ::Selenium::WebDriver::Error::NoSuchElementError => err if options[:raise_on_error] raise end if options[:return_errors] results << err next end results << nil end end # Filter results, if necessary return multifind_filter_results(options, results) end
Private Instance Methods
Applies the :check_element filter
# File lib/unobtainium-multifind/multifind.rb, line 204 def apply_filter(elem, options) if elem.nil? return elem end if elem.is_a?(::Selenium::WebDriver::Error::NoSuchElementError) return elem end if elem.send(options[:check_element]) return elem end return nil end
Collapses results to only return what's specified by :find.
# File lib/unobtainium-multifind/multifind.rb, line 174 def multifind_collapse_results(options, results) # That was easy! if options[:find] == :all return results end # Filtering :first and :last is identical, except we go backwards # through the results array for :last. if options[:find] == :last results.reverse! end # We now return the first non-nil, non-error result results.each do |result| if result.nil? next end if result.is_a?(::Selenium::WebDriver::Error::NoSuchElementError) next end return [result] end # If we're here then we have no results, but want :first # or :last. An empty result is appropriate. return [] end
Filters results from multifind; this largely means honouring the :find option.
# File lib/unobtainium-multifind/multifind.rb, line 151 def multifind_filter_results(options, results) results = multifind_collapse_results(options, results) # If we're only checking for existence, we're done here. if options[:check_element] == :exists? return results end # Filter all results according to the :check_element option filtered = results.map do |result| if result.is_a? Array next result.map do |inner| next apply_filter(inner, options) end end next apply_filter(result, options) end return filtered end
Distinguishes between option hashes and selectors by detecting Hash arguments with keys from DEFAULT_OPTIONS
. Those are considered to be options, and merged with any preceding option hashes, where latter occurrences overwrite earlier ones.
# File lib/unobtainium-multifind/multifind.rb, line 100 def multifind_parse_options(*args) # Sanity if @multifind_options.nil? @multifind_options = DEFAULT_OPTIONS end # Distinguish between options and selectors options = {} selectors = [] args.each do |arg| # Let the underlying API handle all non-Hashes if not arg.is_a?(Hash) selectors << arg next end # See if it contains any of the keys we care about option_keys = DEFAULT_OPTIONS.keys diff = option_keys - arg.keys if diff != option_keys options.merge!(arg) next end selectors << arg end options = @multifind_options.merge(options) options = DEFAULT_OPTIONS.merge(options) # Ensure that the 'find' option contains correct # values only. if not [:all, :first, :last].include?(options[:find]) raise ArgumentError, ":find option must be one of :all, :first or "\ ":last, but is: #{options[:find]}" end # Ensure that 'check_element' contains only valid options. elem_klass = ::Selenium::WebDriver::Element if options[:check_element] != :exists? and not elem_klass.instance_methods.include?(options[:check_element]) raise ArgumentError, ":check_element must either be :exists? or "\ "a boolean method that ::Selenium::WebDriver::Element responds to, "\ "but got: #{options[:check_element]}" end return options, selectors end