=begin
license
---------------------------------------------------------------------------
Copyright (c) 2004-2005, Paul Rogers and Bret Pettichord
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names Paul Rogers, Bret Pettichord nor the names of contributors to
this software may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------
(based on BSD Open Source License)
=end
# This is Watir, Web Application Testing In Ruby
# Home page is http://wtr.rubyforge.org
#
# Version "$Revision: 1.211.2.2 $"
#
# Typical usage:
# # include the controller
# require "watir"
# # go to the page you want to test
# ie = Watir::IE.start("http://myserver/mypage")
# # enter "Paul" into an input field named "username"
# ie.text_field(:name, "username").set("Paul")
# # enter "Ruby Co" into input field with id "company_ID"
# ie.text_field(:id ,"company_ID").set("Ruby Co")
# # click button that has a caption of "Cancel"
# ie.button(:value, "Cancel").click
#
# The ways that are available to identify an html object depend upon the object type, but include
# :id used for an object that has an ID attribute -- this is the best way!
# :name used for an object that has a name attribute.
# :value value of text fields, captions of buttons
# :index finds the nth object of the specified type - eg button(:index , 2) finds the second button. This is 1 based.
# :beforeText finds the object immeditaley before the specified text. Doesnt work if the text is in a table cell
# :afterText finds the object immeditaley after the specified text. Doesnt work if the text is in a table cell
#
# These 2 web sites provide info on Internet Explorer and on the DOM as implemented by Internet Explorer
# http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/webbrowser.asp
# http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/overview/overview.asp
# command line options:
#
# -b (background) Run Internet Explorer invisible
# -f (fast) Run tests fast
# -x (spinner) Add a spinner that displays when pages are waiting to be loaded.
require 'win32ole'
require 'logger'
require 'watir/winClicker'
require 'watir/exceptions'
class String
def matches (x)
return self == x
end
end
class Regexp
def matches (x)
return self.match(x)
end
end
# ARGV needs to be deleted to enable the Test::Unit functionality that grabs
# the remaining ARGV as a filter on what tests to run.
# Note: this means that watir must be require'd BEFORE test/unit.
def command_line_flag(switch)
setting = ARGV.include?(switch)
ARGV.delete(switch)
return setting
end
# Constant to make Internet explorer minimisez. -b stands for background
$HIDE_IE = command_line_flag('-b')
# Constant to enable/disable the spinner
$ENABLE_SPINNER = command_line_flag('-x')
# Constant to set fast speed
$FAST_SPEED = command_line_flag('-f')
# Eat the -s command line switch (deprecated)
command_line_flag('-s')
module Watir
include Watir::Exception
# BUG: this won't work right until the null objects are pulled out
def exists?
begin
yield
true
rescue
false
end
end
class WatirLogger < Logger
def initialize( filName , logsToKeep, maxLogSize )
super( filName , logsToKeep, maxLogSize )
self.level = Logger::DEBUG
self.datetime_format = "%d-%b-%Y %H:%M:%S"
self.debug("Watir starting")
end
end
class DefaultLogger < Logger
def initialize()
super(STDERR)
self.level = Logger::WARN
self.datetime_format = "%d-%b-%Y %H:%M:%S"
self.info "Log started"
end
end
# This class displays the spinner object that appears in the console when a page is being loaded
class Spinner
def initialize(enabled = true)
@s = [ "\b/" , "\b|" , "\b\\" , "\b-"]
@i=0
@enabled = enabled
end
# reverse the direction of spinning
def reverse
@s.reverse!
end
def spin
print self.next if @enabled
end
# get the next character to display
def next
@i=@i+1
@i=0 if @i>@s.length-1
return @s[@i]
end
end
# This module contains the factory methods that are used to access most html objects
#
# For example, to access a button on a web page that has the following html
#
#
# the following watir code could be used
#
# ie.button(:name, 'b1').click
#
# or
#
# ie.button(:value, 'Click Me').to_s
#
# there are many methods available to the Button object
#
# Is includable for classes that have @ieController, document and document.body
module SupportsSubElements
include Watir::Exception
# this method returns the real Internet Explorer object, allowing access to objects, properties and methods that Watir doesnot support
def ie
return @ieController
end
# write the specified string to the log, assuming a logger has been setup using IE#set_logger
def log ( what )
@ieController.logger.debug( what ) if @logger
end
# this method causes Watir to wait until Internet Explorer has finished the action
def wait( noSleep = false )
@ieController.wait( noSleep )
end
def process_default(default_attribute, how, what)
if what == nil
what = how
how = default_attribute
end
return how, what
end
private :process_default
# this method is the main way of accessing a frame
# * how - how the frame is accessed. This can also just be the name of the frame
# * what - what we want to access.
#
# Typical usage:
#
# ie.frame(:index, 1)
# ie.frame(:name , 'main_frame')
# ie.frame('main_frame') # in this case, just a name is supplied
def frame(how, what=nil)
how, what = process_default :name, how, what
return Frame.new(self, how, what)
end
# this method is used to access a form.
# available ways of accessing it are, :index , :name, :id, :method, :action
# * how - symbol - WHat mecahnism we use to find the form, one of the above. NOTE if what is not supplied this parameter is the NAME of the form
# * what - String - the text associated with the symbol
def form(how, what=nil)
how, what = process_default :name, how, what
return Form.new(self, how, what)
end
# This method is used to get a table from the page.
# :index (1 based counting)and :id are supported.
# NOTE :name is not supported, as the table tag does not have a name attribute. It is not part of the DOM.
# :index can be used when there are multiple tables on a page.
# The first form can be accessed with :index 1, the second :index 2, etc.
# * how - symbol - the way we look for the table. Supported values are
# - :id
# - :index
# * what - string the thing we are looking for, ex. id or index of the object we are looking for
def table( how, what )
return Table.new( self , how, what)
end
# this is the main method for accessing the tables iterator. It returns a Tables object
#
# Typical usage:
#
# ie.tables.each { |t| puts t.to_s } # iterate through all the tables on the page
# ie.tables[1].to_s # goto the first table on the page
# ie.tables.length # show how many tables are on the page. Tables that are nested will be included in this
def tables()
return Tables.new(self)
end
# this method accesses a table cell.
# how - symbol - how we access the cell, :id is supported
#
# returns a TableCell Object
def cell( how, what )
return TableCell.new( self, how, what)
end
# this method accesses a table row.
# how - symbol - how we access the row, :id is supported
#
# returns a TableRow object
def row( how, what )
return TableRow.new( self, how, what)
end
# This is the main method for accessing a button. Often declared as an tag.
# * how - symbol - how we access the button
# * what - string, int or re , what we are looking for,
# Returns a Button object.
#
# Valid values for 'how' are
#
# :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
# index is 1 based
# :name - find the item using the name attribute
# :id - find the item using the id attribute
# :value - find the item using the value attribute ( in this case the button caption)
# :caption - same as value
# :beforeText - finds the item immediately before the specified text
# :afterText - finds the item immediately after the specified text
#
# Typical Usage
#
# ie.button(:id, 'b_1') # access the button with an ID of b_1
# ie.button(:name, 'verify_data') # access the button with a name of verify_data
# ie.button(:value, 'Login') # access the button with a value (the text displayed on the button) of Login
# ie.button(:caption, 'Login') # same as above
# ie.button(:value, /Log/) # access the button that has text matching /Log/
# ie.button(:index, 2) # access the second button on the page ( 1 based, so the first button is accessed with :index,1)
#
# if only a single parameter is supplied, then :value is used
#
# ie.button('Click Me') # access the button with a value of Click Me
def button(how, what=nil)
how, what = process_default :value, how, what
return Button.new(self, how, what)
end
# this is the main method for accessing the buttons iterator. It returns a Buttons object
#
# Typical usage:
#
# ie.buttons.each { |b| puts b.to_s } # iterate through all the buttons on the page
# ie.buttons[1].to_s # goto the first button on the page
# ie.buttons.length # show how many buttons are on the page.
def buttons()
return Buttons.new(self)
end
# This is the main method for accessing a file field. Usually an HTML tag.
# * how - symbol - how we access the field , :index, :id, :name etc
# * what - string, int or re , what we are looking for,
#
# returns a FileField object
#
# Typical Usage
#
# ie.file_field(:id, 'up_1') # access the file upload field with an ID of up_1
# ie.file_field(:name, 'upload') # access the file upload field with a name of upload
# ie.file_field(:index, 2) # access the second file upload on the page ( 1 based, so the first field is accessed with :index,1)
#
def file_field(how , what)
return FileField.new(self , how, what)
end
# this is the main method for accessing the file_fields iterator. It returns a FileFields object
#
# Typical usage:
#
# ie.file_fields.each { |f| puts f.to_s } # iterate through all the file fields on the page
# ie.file_fields[1].to_s # goto the first file field on the page
# ie.file_fields.length # show how many file fields are on the page.
def file_fields()
return FileFields.new(self)
end
# This is the main method for accessing a text field. Usually an HTML tag. or a text area - a