Class: WebMinion::CapybaraBot

Inherits:
Bot
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/web_minion/bots/capybara_bot.rb

Instance Attribute Summary collapse

Attributes inherited from Bot

#config

Instance Method Summary collapse

Methods inherited from Bot

#execute_step

Constructor Details

#initialize(config = {}) ⇒ CapybaraBot

Initializes a CapybaraBot

Parameters:

  • config (Hash) (defaults to: {})

    the configuration for the CapybaraBot

  • options (Hash)

    a customizable set of options



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/web_minion/bots/capybara_bot.rb', line 16

def initialize(config = {})
  super(config)
  @driver = config.fetch("driver").to_sym

  if block_given?
    yield
  else
    Capybara.register_driver @driver do |app|
      Capybara::Selenium::Driver.new(app, browser:  @driver)
    end unless Capybara.drivers.include?(@driver)
  end

  @bot = Capybara::Session.new(@driver)
  @bot.driver.resize(config["dimensions"]["width"], config["dimensions"]["height"]) if config["dimensions"]
end

Instance Attribute Details

#botObject (readonly)

Returns the value of attribute bot.



8
9
10
# File 'lib/web_minion/bots/capybara_bot.rb', line 8

def bot
  @bot
end

Instance Method Details

#body_includes(target, value, element) ⇒ Boolean

Tests if the body includes the value or values provided.

Parameters:

  • target (String)

    the target

  • value (String, Regexp, Array[String, Regexp])

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Boolean)


295
296
297
298
299
300
301
302
303
# File 'lib/web_minion/bots/capybara_bot.rb', line 295

def body_includes(target, value, element)
  if value.is_a?(Array)
    # FIXME: this should probably return true if all the values exist.
    val_check_arr = value.map { |v| body_includes(target, v, element) }
    val_check_arr.uniq.include?(true)
  else
    !!(body.index(value) && body.index(value) > 0)
  end
end

#click(target, _value, _element) ⇒ nil

Clicks the provided target.

Parameters:

  • target (String)

    the target (css or xpath) to be clicked

  • _value (String)

    the value (unused)

  • _element (Capybara::Node::Element)

    the element (unused)

Returns:

  • (nil)


52
53
54
# File 'lib/web_minion/bots/capybara_bot.rb', line 52

def click(target, _value, _element)
  @bot.click_link_or_button(target)
end

#click_button_in_form(target, _value, element) ⇒ nil

Clicks the button in the provided form

Parameters:

  • target (String)

    the target (css or xpath) to be clicked

  • _value (String)

    the value (unused)

  • element (Capybara::Node::Element)

    the element (form) containing the target

Returns:

  • (nil)


62
63
64
# File 'lib/web_minion/bots/capybara_bot.rb', line 62

def click_button_in_form(target, _value, element)
  element.find(target).click
end

#fill_in_input(target, value, element) ⇒ Capybara::Node::Element

Fills in a input element

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Capybara::Node::Element)

Raises:



164
165
166
167
168
169
170
171
# File 'lib/web_minion/bots/capybara_bot.rb', line 164

def fill_in_input(target, value, element)
  key, input_name = target.first
  input = element.find("input[#{key}='#{input_name}']")
  raise(NoInputFound, "For target: #{target}") unless input
  input.set value

  element
end

#get_field(target, _value, element) ⇒ Capybara::Node::Element

Finds the form field for a given element.

Parameters:

  • target (String)

    the target (name) of the field

  • _value (String)

    the value (unused)

  • element (Capybara::Node::Element)

    the element containing the field

Returns:

  • (Capybara::Node::Element)


153
154
155
156
# File 'lib/web_minion/bots/capybara_bot.rb', line 153

def get_field(target, _value, element)
  # raise no element passed in? Invalid element?
  element.find_field(target)
end

#get_form(target, _value, _element) ⇒ Capybara::Node::Element

Gets a form element

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Capybara::Node::Element)


133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/web_minion/bots/capybara_bot.rb', line 133

def get_form(target, _value, _element)
  if target.is_a?(Hash)
    type, target = target.first
    return @bot.find(type, target)
  elsif target.is_a?(String)
    index = %w(first last).index(target)
    return @bot.find(target) if index < 0
  end

  index = target if index < 0

  @bot.find_all("form")[index]
end

#go(target, _value, _element) ⇒ nil

Goes to the provided url

Parameters:

  • target (String)

    the target (URL) of the site to visit.

  • _value (String)

    the value (unused)

  • _element (Capybara::Node::Element)

    the element (unused)

Returns:

  • (nil)


42
43
44
# File 'lib/web_minion/bots/capybara_bot.rb', line 42

def go(target, _value, _element)
  @bot.visit(target)
end

#pageObject



32
33
34
# File 'lib/web_minion/bots/capybara_bot.rb', line 32

def page
  @bot.html
end

#save_page_html(_target, value, _element) ⇒ String

Saves the current page.

Examples:

bot.save_html(nil, "/tmp/myfile-%{timestamp}.html")
# => "/tmp/myfile-%{timestamp}.html"

Parameters:

  • _target (String)

    the target (unused)

  • value (String)

    the value, i.e. the filename

  • _element (Capybara::Node::Element)

    the element (unused)

Returns:

  • (String)


99
100
101
102
# File 'lib/web_minion/bots/capybara_bot.rb', line 99

def save_page_html(_target, value, _element)
  filename = value % { timestamp: Time.now.strftime("%Y-%m-%d_%H-%M-%S") }
  @bot.save_page(filename)
end

#save_value(target, value, _element, val_hash) ⇒ Hash

Saves a value to a given hash

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Hash)


110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/web_minion/bots/capybara_bot.rb', line 110

def save_value(target, value, _element, val_hash)
  target_type = %r{^/} =~ target ? :xpath : :css
  elements = @bot.find_all(target_type, target)
  return val_hash if elements.empty?

  val_hash[value.to_sym] = if elements.size == 1
                             Nokogiri::XML(elements.first["outerHTML"]).children.first
                           else
                             val_hash[value.to_sym] = elements.map { |e| Nokogiri::XML(e["outerHTML"]).children.first }
                           end

  val_hash
end

#select_checkbox(target, _value, element) ⇒ nil

Checks a checkbox

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (nil)


224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/web_minion/bots/capybara_bot.rb', line 224

def select_checkbox(target, _value, element)
  if target.is_a?(Array)
    target.each do |tar|
      key, value = tar.first
      element.find(:css, "input[#{key}='#{value}']").set(true)
    end
  else
    begin
      element.check(target)
    rescue Capybara::ElementNotFound
      element.find(:css, target).set(true)
    end
  end
end

#select_field(target, _value, element) ⇒ Capybara::Node::Element

Selects the options from a <select> input.Clicks/

Parameters:

  • target (String)

    the target, the label or value for the Select Box

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Capybara::Node::Element)


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/web_minion/bots/capybara_bot.rb', line 191

def select_field(target, _value, element)
  # NOTE: Capybara selects from the option's label, i.e. the text, not the
  #       option value. If it can't find the matching text, it raises a
  #       Capybara::ElementNotFound error. In this situation, we should find
  #       that select option manually.
  #
  #       <select>
  #         <option value="1">Hello</option>
  #         <option value="2">Hi</option>
  #       </select>
  #
  #       These two commands are equivalent
  #
  #       1. element.select("Hello")
  #       2. element.find("option[value='1']").select_option
  if target.is_a?(Hash)
    key, value = target.first
    element.find("option[#{key}='#{value}']").select_option
  else
    element.select(target)
  end
rescue Capybara::ElementNotFound
  element.find("option[value='#{target}']").select_option
rescue Capybara::Ambiguous
  raise(MultipleOptionsFoundError, "For target: #{target}")
end

#select_first_radio_button(_target, _value, element) ⇒ Capybara::Node::Element

Selects the first radio button

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Capybara::Node::Element)


270
271
272
273
274
275
# File 'lib/web_minion/bots/capybara_bot.rb', line 270

def select_first_radio_button(_target, _value, element)
  radio = element.find(:css, "input[type='radio']", match: :first)
  radio.set(true)

  radio
end

#select_radio_button(target, value, element) ⇒ Capybara::Node::Element

Select a radio button

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Capybara::Node::Element)


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/web_minion/bots/capybara_bot.rb', line 245

def select_radio_button(target, value, element)
  if target.is_a?(Array)
    return target.map { |tar| select_radio_button(tar, value, element) }
  elsif target.is_a?(Hash)
    key, value = target.first
    radio = element.find(:css, "input[#{key}='#{value}']")
    radio.set(true)
  else
    begin
      element.choose(target)
    rescue Capybara::ElementNotFound
      radio = element.find(:css, target)
      radio.set(true)
    end
  end

  radio || element.find(target)
end

#set_file_upload(target, value, element) ⇒ nil

Sets the file to be uploaded

Parameters:

  • target (String)

    the target

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (nil)

Raises:

  • (Errno::ENOENT)


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/web_minion/bots/capybara_bot.rb', line 72

def set_file_upload(target, value, element)
  if target.is_a?(String) && %w(first last).include?(target)
    file_upload = element.find_all(:css, "input[type='file']").send(target)
  elsif target.is_a?(String)
    target_type = %r{^//} =~ target ? :xpath : :css
    file_upload = element.find(target_type, target, match: :first)
  elsif target.is_a?(Hash)
    key, input_name = target.first
    locator = "input[#{key}='#{input_name}']"
    file_upload = element.find(:css, locator, match: :first)
  end

  raise Errno::ENOENT unless File.exist?(File.absolute_path(value))

  file_upload.set(File.absolute_path(value))
end

#submit(_target, _value, element) ⇒ nil

Submit a form

Parameters:

  • _target (String)

    the target (unused)

  • _value (String)

    the value (unused)

  • element (Capybara::Node::Element)

    the element

Returns:

  • (nil)


179
180
181
182
183
# File 'lib/web_minion/bots/capybara_bot.rb', line 179

def submit(_target, _value, element)
  element.find('input[type="submit"]').click
rescue Capybara::ElementNotFound
  element.click
end

#url_equals(_target, value, _element) ⇒ Boolean

Tests if the value provided equals the current URL.

Parameters:

  • _target (String)

    the target (unused)

  • value (String)

    the value

  • _element (Capybara::Node::Element)

    the element (unused)

Returns:

  • (Boolean)


285
286
287
# File 'lib/web_minion/bots/capybara_bot.rb', line 285

def url_equals(_target, value, _element)
  !!(@bot.current_url == value)
end

#value_equals(_target, value, element) ⇒ Boolean

Tests if the value provided equals the value of the element

Parameters:

  • _target (String)

    the target (unused)

  • value (String)

    the value

  • element (Capybara::Node::Element)

    the element

Returns:

  • (Boolean)


311
312
313
# File 'lib/web_minion/bots/capybara_bot.rb', line 311

def value_equals(_target, value, element)
  !!(element && (element.value == value))
end