Module: Druid

Includes:
Assist, ElementLocators, PagePopulator
Defined in:
lib/druid.rb,
lib/druid/assist.rb,
lib/druid/version.rb,
lib/druid/elements.rb,
lib/druid/accessors.rb,
lib/druid/elements/div.rb,
lib/druid/page_factory.rb,
lib/druid/elements/area.rb,
lib/druid/elements/bold.rb,
lib/druid/elements/form.rb,
lib/druid/elements/link.rb,
lib/druid/elements/span.rb,
lib/druid/elements/audio.rb,
lib/druid/elements/image.rb,
lib/druid/elements/label.rb,
lib/druid/elements/media.rb,
lib/druid/elements/table.rb,
lib/druid/elements/video.rb,
lib/druid/javascript/yui.rb,
lib/druid/page_populator.rb,
lib/druid/elements/button.rb,
lib/druid/elements/canvas.rb,
lib/druid/elements/italic.rb,
lib/druid/elements/option.rb,
lib/druid/nested_elements.rb,
lib/druid/element_locators.rb,
lib/druid/elements/element.rb,
lib/druid/elements/heading.rb,
lib/druid/javascript/jquery.rb,
lib/druid/locator_generator.rb,
lib/druid/elements/check_box.rb,
lib/druid/elements/list_item.rb,
lib/druid/elements/paragraph.rb,
lib/druid/elements/table_row.rb,
lib/druid/elements/text_area.rb,
lib/druid/section_collection.rb,
lib/druid/elements/file_field.rb,
lib/druid/elements/table_cell.rb,
lib/druid/elements/text_field.rb,
lib/druid/elements/select_list.rb,
lib/druid/javascript/angularjs.rb,
lib/druid/javascript/prototype.rb,
lib/druid/elements/hidden_field.rb,
lib/druid/elements/ordered_list.rb,
lib/druid/elements/radio_button.rb,
lib/druid/elements/unordered_list.rb,
lib/druid/javascript_framework_facade.rb

Overview

require ‘watir/extensions/alerts’

Module that when included adds functionality to a page object. This module will add numerous class and instance methods that you use to define and interact with web pages.

If we have a login page with a username and password textfield and a login button we might define our page like the one below. We can then interact with the object using the generated methods.

Examples:

Login page example

class LoginPage
  include Druid

  text_field(:username, :id => 'user')
  text_field(:password, :id => 'pass')
  button(:login, :value => 'Login')
end

...

browser = Watir::Browser.new :firefox
login_page = LoginPage.new(browser)
login_page.username = 'tim'
login_page.password = 'sheng'
login_page.login

See Also:

Defined Under Namespace

Modules: Accessors, Assist, ElementLocators, Elements, Javascript, JavascriptFrameworkFacade, LocatorGenerator, NestedElements, PageFactory, PagePopulator Classes: SectionCollection

Constant Summary collapse

VERSION =
"1.0.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PagePopulator

#populate_page_with

Methods included from ElementLocators

#element

Methods included from Assist

#area_for, #areas_for, #audio_for, #audios_for, #b_for, #b_text_for, #bs_for, #button_for, #buttons_for, #canvas_for, #canvass_for, #cell_for, #cell_text_for, #cells_for, #check_checkbox, #checkbox_checked?, #checkbox_for, #checkboxs_for, #click_area_for, #click_button_for, #click_link_for, #div_for, #div_text_for, #divs_for, #element_for, #elements_for, #file_field_for, #file_field_value_set, #file_fields_for, #form_for, #forms_for, #h1_for, #h1_text_for, #h1s_for, #h2_for, #h2_text_for, #h2s_for, #h3_for, #h3_text_for, #h3s_for, #h4_for, #h4_text_for, #h4s_for, #h5_for, #h5_text_for, #h5s_for, #h6_for, #h6_text_for, #h6s_for, #hidden_field_for, #hidden_field_value_for, #hidden_fields_for, #i_for, #i_text_for, #image_for, #image_loaded_for, #images_for, #is_for, #label_for, #label_text_for, #labels_for, #link_for, #links_for, #list_item_for, #list_item_text_for, #list_items_for, #ordered_list_for, #ordered_list_text_for, #ordered_lists_for, #page_for, #pages_for, #paragraph_for, #paragraph_text_for, #paragraphs_for, #radio_button_for, #radio_buttons_for, #radio_selected?, #row_for, #row_text_for, #rows_for, #select_list_for, #select_list_value_for, #select_list_value_set, #select_lists_for, #select_radio, #span_for, #span_text_for, #spans_for, #svg_for, #svgs_for, #table_for, #table_text_for, #tables_for, #text_area_for, #text_area_value_for, #text_area_value_set, #text_areas_for, #text_field_for, #text_field_value_for, #text_field_value_set, #text_fields_for, #uncheck_checkbox, #unordered_list_for, #unordered_list_text_for, #unordered_lists_for, #video_for, #videos_for

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

extend Forwardable



45
46
47
# File 'lib/druid.rb', line 45

def method_missing(method, *args, &block)
  @root_element.send(method, *args, &block)
end

Instance Attribute Details

#driverWatir::Browser (readonly)

Returns the drvier passed to the constructor.

Returns:

  • (Watir::Browser)

    the drvier passed to the constructor



58
59
60
# File 'lib/druid.rb', line 58

def driver
  @driver
end

Class Method Details

.add_framework(key, framework) ⇒ Object

Add a new javascript framework to druid. The module passed in must adhere to the same prototype as the JQuery and Prototype modules.

subsequent calls the required actions.

Parameters:

  • the (Symbol)

    name used to reference the framework in

  • a (Module)

    module that has the necessary methods to perform



142
143
144
# File 'lib/druid.rb', line 142

def self.add_framework(key, framework)
  Druid::JavascriptFrameworkFacade.add_framework(key, framework)
end

.default_element_waitObject

Returns the default timeout for element level Waits



119
120
121
# File 'lib/druid.rb', line 119

def self.default_element_wait
  @element_wait ||= 5
end

.default_element_wait=(timeout) ⇒ Object

Sets the default timeout for element level Waits



112
113
114
# File 'lib/druid.rb', line 112

def self.default_element_wait=(timeout)
  @element_wait = timeout
end

.default_page_waitObject

Return the default timeout for page level Waits



105
106
107
# File 'lib/druid.rb', line 105

def self.default_page_wait
  @page_wait ||= 30
end

.default_page_wait=(timeout) ⇒ Object

Set the default timeout for page level Waits



98
99
100
# File 'lib/druid.rb', line 98

def self.default_page_wait=(timeout)
  @page_wait = timeout
end

.included(cls) ⇒ Object



82
83
84
# File 'lib/druid.rb', line 82

def self.included(cls)
  cls.extend Druid::Accessors
end

.javascript_framework=(framework) ⇒ Object

Set the javascript framework to use when determining number of ajax requests. Valid frameworks are :jquery, :prototype, and :yui, and :angularjs



128
129
130
# File 'lib/druid.rb', line 128

def self.javascript_framework=(framework)
  Druid::JavascriptFrameworkFacade.framework = framework
end

Instance Method Details

#alert(&block) ⇒ String

Override the normal alert popup so it does not occur.

Examples:

message = @page.alert do
  @page.button_that_causes_alert
end

Parameters:

  • block

    a block that has the call that will cause the alert to display

Returns:

  • (String)

    the message that was contained in the alert



248
249
250
251
252
253
254
255
256
257
258
# File 'lib/druid.rb', line 248

def alert(&block)
  # switch_to_frame(frame)
  yield
  value = nil
  if driver.alert.exists?
    value = driver.alert.text
    driver.alert.ok
  end
  # switch_to_default_content(frame)
  value
end

#attach_to_window(identifier, &block) ⇒ Object

Attach to a running window. You can locate the window using either the window’s title or url or index, If it fails to connect to a window it will pause for 1 second and try again.

be the entire url - it can just be the page name like index.html

Examples:

@page.attach_to_window(:title => "other window's title")

Parameters:

  • either (Hash)

    :title or :url or index of the other window. The url does not need to



324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/druid.rb', line 324

def attach_to_window(identifier, &block)
  if identifier.keys.first == :url
    win_id = {identifier.keys.first => /#{Regexp.escape(identifier.values.first)}/}
  else
    win_id = {identifier.keys.first => identifier.values.first}
  end
  begin
    driver.window(win_id).use &block
  rescue
    sleep 1
    driver.window(win_id).use &block
  end
end

#backObject

Go back to the previous page



195
196
197
# File 'lib/druid.rb', line 195

def back
  driver.back
end

#call_block(&block) ⇒ Object



442
443
444
# File 'lib/druid.rb', line 442

def call_block(&block)
  block.arity == 1 ? block.call(self) : self.instance_eval(&block)
end

#confirm(response, &block) ⇒ String

Override the normal confirm popup so it does not occur

Examples:

message = @popup.confirm(true) do
  @page.button_that_causes_confirm
end

Parameters:

  • what (boolean)

    response you want to return back from the confirm popup

  • block

    a block that has the call that will cause the confirm to display

Returns:

  • (String)

    the message that was contained in the confirm



272
273
274
275
276
277
278
279
280
# File 'lib/druid.rb', line 272

def confirm(response, &block)
  yield
  value = nil
  if driver.alert.exists?
    value = driver.alert.text
    response ? driver.alert.ok : driver.alert.close
  end
  value
end

#cookiesWatir::Cookies

Handle cookies

Returns:

  • (Watir::Cookies)


377
378
379
# File 'lib/druid.rb', line 377

def cookies
  driver.cookies
end

#current_urlObject

get the current page url



148
149
150
# File 'lib/druid.rb', line 148

def current_url
  driver.url
end

#element_with_focusObject

Find the element that has focus on the page



341
342
343
344
345
346
# File 'lib/druid.rb', line 341

def element_with_focus
  element = driver.execute_script("return document.activeElement")
  type = element.type.to_sym if element.tag_name.to_sym == :input
  cls = Druid::Elements.element_class_for(element.tag_name, type)
  cls.new(element)
end

#execute_script(script, *args) ⇒ Object

Execute javascript on the browser



308
309
310
311
# File 'lib/druid.rb', line 308

def execute_script(script, *args)
  args.map! { |e| e.kind_of?(Druid::Elements::Element) ? e.element : e }
  driver.execute_script(script, *args)
end

#forwardObject

Go forward to the next page



202
203
204
# File 'lib/druid.rb', line 202

def forward
  driver.forward
end

#htmlObject

Returns the html of the current page



162
163
164
# File 'lib/druid.rb', line 162

def html
  driver.html
end

#in_frame(identifier, frame = nil, &block) ⇒ Object

Identify an element as existing within a frame. A frame parameter is passed to the block and must be passed to the other calls to Druid. You can nest calls to in_frame by passing the frame to the next level.

Examples:

@page.in_frame(:id => 'frame_id') do |frame|
  @page.text_field_element(:id=> 'fname', :frame => frame)
end

Parameters:

  • identifier (Hash)

    how we find the frame. The valid keys are:

    • :id

    • :index

    • :name

  • block

    that contains the calls to elements that exist inside the frame.



404
405
406
407
408
# File 'lib/druid.rb', line 404

def in_frame(identifier, frame=nil, &block)
  frame = [] if frame.nil?
  frame << {frame: identifier}
  block.call(frame)
end

#in_iframe(identifier, frame = nil, &block) ⇒ Object

Identify an element as existing within an iframe. Aframe parameter is passed to the block and must be passed to the other calls to Druid. You can nest calls to in_iframe by passing the frame to the next level.

Examples:

@page.in_iframe(:id => 'frame_id') do |frame|
  @page.text_field_element(:id=> 'fname', :frame => frame)
end

Parameters:

  • identifier (Hash)

    how we find the frame. The valid keys are:

    • :id

    • :index

    • :name

  • block

    that contains the calls to elements that exist inside the frame.



426
427
428
429
430
# File 'lib/druid.rb', line 426

def in_iframe(identifier, frame=nil, &block)
  frame = [] if frame.nil?
  frame << {iframe: identifier}
  block.call(frame)
end

#initialize(root, visit = false) ⇒ Object

Construct a new druid. Prior to browser initialization it will call a method named initialize_accessors if it exists. Upon initialization of the page it will call a method named initialize_page if it exists

Parameters:

  • the (Watir::Browser, Watir:HTMLElement)

    driver/element to use

  • open (bool)

    the page if page_url is set



68
69
70
71
72
73
# File 'lib/druid.rb', line 68

def initialize(root, visit=false)
  initialize_accessors if respond_to?(:initialize_accessors)
  initialize_driver root
  goto if visit && respond_to?(:goto)
  initialize_page if respond_to?(:initialize_page)
end

#initialize_driver(root) ⇒ Object



75
76
77
78
79
# File 'lib/druid.rb', line 75

def initialize_driver root
  @driver = root if root.is_a? Watir::HTMLElement or root.is_a? Watir::Browser
  @root_element = Elements::Element.new root if root.is_a? Watir::HTMLElement
  raise "expect Watir::Browser or Watir::HTMLElement" if not root.is_a? Watir::HTMLElement and not root.is_a? Watir::Browser
end

Override the normal showModalDialog call is it opens a window instead of a dialog. You will need to attach to the new window in order to continue.

Examples:

@page.modal_dialog do
  @page.action_that_spawns_the_modal
end

Parameters:

  • block

    a block that contains the call that will cause the modal dialog.



359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/druid.rb', line 359

def modal_dialog(&block)
  script =
  %Q{
    window.showModalDialog = function(sURL, vArguments, sFeatures) {
      window.dialogArguments = vArguments;
      modalWin = window.open(sURL, 'modal', sFeatures);
      return modalWin;
    }
  }
  driver.execute_script script
  yield if block_given?
end

navigate to the provided url

Parameters:

  • the (String)

    full url to navigate to



91
92
93
# File 'lib/druid.rb', line 91

def navigate_to url
  driver.goto url
end

#prompt(answer, &block) ⇒ String

Override the normal prompt popup so it does not occur

Examples:

message = @popup.prompt("Some Value") do
  @page.button_that_causes_prompt
end

Parameters:

  • the (String)

    value will be setted in the prompt field

  • block

    a block that has the call that will cause the prompt to display

Returns:

  • (String)

    the message that was contained in the prompt



294
295
296
297
298
299
300
301
302
303
# File 'lib/druid.rb', line 294

def prompt(answer, &block)
  yield
  value = nil
  if driver.alert.exists?
    value = driver.alert.text
    driver.alert.set answer
    driver.alert.ok
  end
  value
end

#refreshObject

Refresh current page



176
177
178
# File 'lib/druid.rb', line 176

def refresh
  driver.refresh
end

#respond_to_missing?(method, include_all = false) ⇒ Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/druid.rb', line 49

def respond_to_missing?(method, include_all = false)
  @root_element && @root_element.respond_to?(method) || super
end

#save_screenshot(file_name) ⇒ Object

Save the current screenshot to the provided path. File is saved as a png file.



384
385
386
# File 'lib/druid.rb', line 384

def save_screenshot(file_name)
  driver.screenshot.save(file_name)
end

#switch_to_frame(frame_identifiers) ⇒ Object



432
433
434
435
436
437
438
439
440
# File 'lib/druid.rb', line 432

def switch_to_frame(frame_identifiers)
  unless frame_identifiers.nil?
    frame_identifiers.each do |frame|
      frame_id = frame.values.first
      value = frame_id.values.first
      driver.wd.switch_to.frame(value)
    end
  end
end

#textObject

Returns the text of the current page



155
156
157
# File 'lib/druid.rb', line 155

def text
  driver.text
end

#titleObject

Returns the title of the current page



169
170
171
# File 'lib/druid.rb', line 169

def title
  driver.title
end

#wait(timeout = 5) ⇒ Object

Waits until readyState of document is complete

Examples:

@page.wait

Parameters:

  • timeout (Integer) (defaults to: 5)


188
189
190
# File 'lib/druid.rb', line 188

def wait(timeout = 5)
  driver.wait(timeout = 5)
end

#wait_for_ajax(timeout = Druid.default_page_wait, message = nil) ⇒ Object

wait until there are no pending ajax requests. This requires you to set the javascript framework in advance.

Parameters:

  • the (Numeric)

    amount of time to wait for the block to return true.

  • the (String)

    message to include with the error if we exceed the timeout duration



227
228
229
230
231
232
233
234
235
# File 'lib/druid.rb', line 227

def wait_for_ajax(timeout = Druid.default_page_wait, message = nil)
  end_time = ::Time.now + timeout
  until ::Time.now > end_time
    return if driver.execute_script(Druid::JavascriptFrameworkFacade.pending_requests) == 0
    sleep 1
  end
  message = "Timed out waiting for ajax requests to complete" unless message
  raise message
end

#wait_until(timeout = Druid.default_page_wait, message = nil, &block) ⇒ Object

Wait until the block returns true or times out

Examples:

@page.wait_until(5, 'Success not found on page') do
  @page.text.include? 'Success'
end

Parameters:

  • the (Numeric)

    amount of time to wait for the block to return true

  • the (String)

    message to include with the error if we exceed the timeout duration

  • block

    the block to execute. It should return true when successful.



217
218
219
# File 'lib/druid.rb', line 217

def wait_until(timeout = Druid.default_page_wait, message = nil, &block)
  driver.wait_until(timeout: timeout, message: message, &block)
end