module Druid

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.

@example 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 Druid::Accessors to see what class level methods are added to this module at runtime.

Constants

VERSION

Attributes

driver[R]

@return [Watir::Browser] the drvier passed to the constructor

Public Class Methods

add_framework(key, framework) click to toggle source

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

@param [Symbol] the name used to reference the framework in subsequent calls @param [Module] a module that has the necessary methods to perform the required actions.

# File lib/druid.rb, line 142
def self.add_framework(key, framework)
  Druid::JavascriptFrameworkFacade.add_framework(key, framework)
end
default_element_wait() click to toggle source

Returns the default timeout for element level Waits

# File lib/druid.rb, line 119
def self.default_element_wait
  @element_wait ||= 5
end
default_element_wait=(timeout) click to toggle source

Sets the default timeout for element level Waits

# File lib/druid.rb, line 112
def self.default_element_wait=(timeout)
  @element_wait = timeout
end
default_page_wait() click to toggle source

Return the default timeout for page level Waits

# File lib/druid.rb, line 105
def self.default_page_wait
  @page_wait ||= 30
end
default_page_wait=(timeout) click to toggle source

Set the default timeout for page level Waits

# File lib/druid.rb, line 98
def self.default_page_wait=(timeout)
  @page_wait = timeout
end
included(cls) click to toggle source

@private

# File lib/druid.rb, line 82
def self.included(cls)
  cls.extend Druid::Accessors
end
javascript_framework=(framework) click to toggle source

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

# File lib/druid.rb, line 128
def self.javascript_framework=(framework)
  Druid::JavascriptFrameworkFacade.framework = framework
end
new(root, visit=false) click to toggle source

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

@param [Watir::Browser, Watir:HTMLElement] the driver/element to use @param [bool] open the page if page_url is set

# 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

Public Instance Methods

alert() { || ... } click to toggle source

Override the normal alert popup so it does not occur.

@example

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

@param block a block that has the call that will cause the alert to display @return [String] the message that was contained in the alert

# 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) click to toggle source

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.

@example

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

@param [Hash] either :title or :url or index of the other window. The url does not need to be the entire url - it can just be the page name like index.html

# 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
back() click to toggle source

Go back to the previous page

# File lib/druid.rb, line 195
def back
  driver.back
end
call_block(&block) click to toggle source
# File lib/druid.rb, line 442
def call_block(&block)
  block.arity == 1 ? block.call(self) : self.instance_eval(&block)
end
confirm(response) { || ... } click to toggle source

Override the normal confirm popup so it does not occur

@example

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

@param [boolean] what response you want to return back from the confirm popup @param block a block that has the call that will cause the confirm to display @return [String] the message that was contained in the confirm

# 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
cookies() click to toggle source

Handle cookies

@return [Watir::Cookies]

# File lib/druid.rb, line 377
def cookies
  driver.cookies
end
current_url() click to toggle source

get the current page url

# File lib/druid.rb, line 148
def current_url
  driver.url
end
element_with_focus() click to toggle source

Find the element that has focus on the page

# 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) click to toggle source

Execute javascript on the browser

# 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
forward() click to toggle source

Go forward to the next page

# File lib/druid.rb, line 202
def forward
  driver.forward
end
html() click to toggle source

Returns the html of the current page

# File lib/druid.rb, line 162
def html
  driver.html
end
in_frame(identifier, frame=nil, &block) click to toggle source

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.

@example

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

@param [Hash] identifier how we find the frame. The valid keys are:

* :id
* :index
* :name

@param block that contains the calls to elements that exist inside the frame.

# 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) click to toggle source

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.

@example

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

@param [Hash] identifier how we find the frame. The valid keys are:

* :id
* :index
* :name

@param block that contains the calls to elements that exist inside the frame.

# 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_driver(root) click to toggle source
# 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
method_missing(method, *args, &block) click to toggle source

extend Forwardable

# File lib/druid.rb, line 45
def method_missing(method, *args, &block)
  @root_element.send(method, *args, &block)
end
modal_dialog() { || ... } click to toggle source

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.

@example

@page.modal_dialog do
  @page.action_that_spawns_the_modal
end

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

navigate_to(url) click to toggle source

navigate to the provided url

@param [String] the full url to navigate to

prompt(answer) { || ... } click to toggle source

Override the normal prompt popup so it does not occur

@example

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

@param [String] the value will be setted in the prompt field @param block a block that has the call that will cause the prompt to display @return [String] the message that was contained in the prompt

# 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
refresh() click to toggle source

Refresh current page

# File lib/druid.rb, line 176
def refresh
  driver.refresh
end
respond_to_missing?(method, include_all = false) click to toggle source
Calls superclass method
# 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) click to toggle source

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

# File lib/druid.rb, line 384
def save_screenshot(file_name)
  driver.screenshot.save(file_name)
end
switch_to_frame(frame_identifiers) click to toggle source
# 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
text() click to toggle source

Returns the text of the current page

# File lib/druid.rb, line 155
def text
  driver.text
end
title() click to toggle source

Returns the title of the current page

# File lib/druid.rb, line 169
def title
  driver.title
end
wait(timeout = 5) click to toggle source

Waits until readyState of document is complete

@example

@page.wait

@param [Integer] timeout

# 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) click to toggle source

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

@param [Numeric] the amount of time to wait for the block to return true. @param [String] the message to include with the error if we exceed the timeout duration

# 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) click to toggle source

Wait until the block returns true or times out

@example

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

@param [Numeric] the amount of time to wait for the block to return true @param [String] the message to include with the error if we exceed the timeout duration @param block the block to execute. It should return true when successful.

# 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

Private Instance Methods

root() click to toggle source
# File lib/druid.rb, line 448
def root
  @root_element || driver
end