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.2.3"

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



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

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



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

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



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

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

.default_element_waitObject

Returns the default timeout for element level Waits



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

def self.default_element_wait
  @element_wait ||= 5
end

.default_element_wait=(timeout) ⇒ Object

Sets the default timeout for element level Waits



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

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

.default_page_waitObject

Return the default timeout for page level Waits



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

def self.default_page_wait
  @page_wait ||= 30
end

.default_page_wait=(timeout) ⇒ Object

Set the default timeout for page level Waits



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

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

.included(cls) ⇒ Object



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

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



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

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



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

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



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

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



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

def back
  driver.back
end

#call_block(&block) ⇒ Object



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

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

#clear_cookiesObject

Clear the cookies from the browser



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

def clear_cookies
  driver.cookies.clear
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



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

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

#current_urlObject

get the current page url



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

def current_url
  driver.url
end

#element_with_focusObject

Find the element that has focus on the page



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

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



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

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



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

def forward
  driver.forward
end

#htmlObject

Returns the html of the current page



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

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.



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

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.



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

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



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

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



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

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.



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

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



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

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



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

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



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

def refresh
  driver.refresh
end

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

Returns:

  • (Boolean)


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

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.



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

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

#switch_to_frame(frame_identifiers) ⇒ Object



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

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



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

def text
  driver.text
end

#titleObject

Returns the title of the current page



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

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)


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

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



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

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.



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

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