Module: LapisLazuli::BrowserModule::Find

Includes:
ArgParse
Included in:
LapisLazuli::Browser
Defined in:
lib/lapis_lazuli/browser/find.rb

Overview

Find functionality for LapisLazuli::Browser. Don’t use outside of that class.

Constant Summary

Constants included from ArgParse

ArgParse::ERROR_OPTIONS

Instance Method Summary collapse

Methods included from ArgParse

#make_list_from_item, #make_list_from_nested, #parse_args

Instance Method Details

#find(*args) ⇒ Object

Same as find_all, but returns only one element.

The function supports an additional parameter :pick that can be one of :first, :last or :random, or a numeric value.

The parameter determines whether the first, last or a random element from the find_all result set is returned. If a numeric value is given, the nth element is returned.

The default for :pick is :first



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/lapis_lazuli/browser/find.rb', line 74

def find(*args)
  # Parse args into options
  options = {
    :pick => :first,
  }
  options = parse_find_options(options, *args)
  pick, options = pick_which?(options)

  # Pick one of the find all results
  return pick_one(pick, find_all(options))
end

#find_all(*args) ⇒ Object

Finds all elements corresponding to some specification; the supported specifications include the ones accepted by Watir::Browser.elements.

Possible specifications are:

  • Watir specifications, e.g. { :tag_name => ‘a’, … }

  • An alternative to the Watir specifications: { :a => { :id => /some-id/ } } <=> { :tag_name => ‘a’, :id => /some-id/ } Note that the value can be an empty hash, e.g. { :a => {} } This method uses Watir selectors.

  • A shortcut version searching for a tag by name, id or content: { :a => ‘name-or-id-or-content’ } This method uses XPath.

  • A like specifcation. The value of :like is a hash, which must at least contain an :element name; in addition, an optional :attribute and :include field further filters the results. { :like => => ‘a’, :attribute => ‘class’, :include => ‘foo’ } This method uses XPath.

  • A shorthand for the above using an array that’s interpreted to contain :element, :attribute and :include in order. { :like => [‘a’, ‘class’, ‘foo’] } This method also uses XPath.

In addition to the above, you can include the following parameters:

  • :filter_by expects a symbol that the elements respond to; if calling the method returns true, the element is returned, otherwise it is ignored. Use e.g. { :filter_by => :present? }

  • :throw one of true, false. Default is true.



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/lapis_lazuli/browser/find.rb', line 50

def find_all(*args)
  # Parse args into options
  options = parse_find_options({}, *args)
  throw_opt, options = do_throw?(options)

  # Find filtered.
  opts, func = find_lambda_filtered(options[:selectors][0])

  # Dispatch the call & handle errors
  return dispatch_call(throw_opt, "Error in find", options, opts, func)
end

#multi_find(*args) ⇒ Object

Same as multi_find_all, but accepts the :pick parameter as find does.



127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/lapis_lazuli/browser/find.rb', line 127

def multi_find(*args)
  # Parse args into options
  options = {
    :mode => :match_one,
    :pick => :first,
  }
  options = parse_find_options(options, *args)
  pick, options = pick_which?(options)

  # Pick one of the find all results
  return pick_one(pick, multi_find_all(options))
end

#multi_find_all(*args) ⇒ Object

Same as find_all, but accepts an array of selectors.

The function has two modes:

  1. It either tries to find a match for every selector, or

  2. It tries to find a single match from all selectors.

The mode is specified with the optional :mode parameter, which can be one of :match_all or :match_any. The default mode is :match_any.

Note that if you specify the :mode, you can’t simultaneously pass a list of selectors easily, e.g. the following does not parse:

multi_find_all(:mode => :match_all, selector1, selector2)

Instead use:

multi_find_all(:mode => :match_all, :selectors => [selector1, selector2])

However, using the default mode, you can simplify it all:

multi_find_all(selector1, selector2)


109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/lapis_lazuli/browser/find.rb', line 109

def multi_find_all(*args)
  # Parse args into options
  options = {
    :mode => :match_any,
  }
  options = parse_find_options(options, *args)
  throw_opt, options = do_throw?(options)

  # Find all for the given selectors
  opts, func = multi_find_lambda(options)

  # Dispatch the call & handle errors
  return dispatch_call(throw_opt, "Error in multi_find", options, opts, func)
end

#pick_one(pick, elems) ⇒ Object

Pick implementation for find and multi_find, but can be used standalone.

pick may be one of :first, :last, :random or a numeric index. Returns the element from the collection corresponding to the pick parameter.



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/lapis_lazuli/browser/find.rb', line 146

def pick_one(pick, elems)
  case pick
  when :first
    return elems.first
  when :last
    return elems.last
  when :random
    return elems.to_a.shuffle.first
  else
    if pick.is_a? Numeric
      return elems[pick.to_i]
    else
      options[:message] = optional_message("Invalid :pick value #{pick}.", options)
      options[:groups] = ['find', 'pick']
      world.error(options)
    end
  end
end