Sunteți pe pagina 1din 141

Sahi Pro V 4.

2

Web Automation and Testing Tool
User Manual




Sahi Pro Tyto Software Pvt. Ltd. 2

Contents
Sahi - Introduction ............................................................................................................................................................................. 7
Sahi Architecture ....................................................................................................................................................... 8
Sahi Advantages .................................................................................................................................................................................. 9
Browser Platform Independence ............................................................................................................................... 9
Smart Identification Mechanisms .............................................................................................................................. 9
UI Relations .............................................................................................................................................................. 9
Parallel Playback ....................................................................................................................................................... 9
Getting Started .................................................................................................................................................................................. 10
Prerequisites ............................................................................................................................................................ 10
Download Sahi Pro .................................................................................................................................................. 10
Installation of Sahi .................................................................................................................................................. 10
Starting Sahi ...................................................................................................................................................................................... 15
Recording through Sahi ................................................................................................................................................................ 16
Playing back through Sahi .......................................................................................................................................................... 21
Running a test from the controller ........................................................................................................................... 21
View Logs ............................................................................................................................................................... 22
Creating a Suite File ....................................................................................................................................................................... 23
Running a test or suite from command line ............................................................................................................. 24
Running a test or suite using ant: ............................................................................................................................ 25
Distributing tests across different machines using ant: ..................................................................... 26
Load testing using ant: ........................................................................................................................ 27
Sahi Pro Controller .......................................................................................................................................................................... 29
Recorder Tab ........................................................................................................................................................... 29
The Anchor Button .................................................................................................................................................. 30
Example ............................................................................................................................................... 30
Using the Sahi Script Editor .................................................................................................................................... 31


Sahi Pro Tyto Software Pvt. Ltd. 3

Playback Tab ........................................................................................................................................................... 33
Running Tests on multiple machines ...................................................................................................................................... 34
Reports .................................................................................................................................................................... 35
Database Report ...................................................................................................................................................... 36
Sahi Scripting Basics ...................................................................................................................................................................... 39
Statements: .............................................................................................................................................................. 39
Variable declaration: ............................................................................................................................................... 39
Function declaration: ............................................................................................................................................... 39
Comments: .............................................................................................................................................................. 39
if statements: ........................................................................................................................................................... 40
for loops: ................................................................................................................................................................. 40
while loops: ............................................................................................................................................................. 41
Including another Sahi script file: ........................................................................................................................... 41
Advanced Scripting ......................................................................................................................................................................... 42
Perform all actions using Browser Action APIs. ..................................................................................................... 42
Use _set to store a variable with data from browser ................................................................................................ 42
Using custom functions that access the DOM. ........................................................................................................ 42
Prefix a $ sign before variables which are passed to sahi functions. ....................................................................... 42
Exception Handling using try-catch ........................................................................................................................................ 43
Recovering without try-catch using _setRecovery ............................................................................................................ 44
Script Lifecycle Call Back Functions........................................................................................................................................ 45
Sahi Pro Excel Framework .......................................................................................................................................................... 46
Sample Excel Sheet ................................................................................................................................................. 46
Loading Sahi script libraries .................................................................................................................................... 46
Executing the Excel Sheet ....................................................................................................................................... 47
Play back reports/logs ............................................................................................................................................. 47
IMPORTANT NOTES ............................................................................................................................ 48


Sahi Pro Tyto Software Pvt. Ltd. 4

Syntax ...................................................................................................................................................................... 49
Variables ............................................................................................................................................. 50
SetUp and TearDown .......................................................................................................................... 50
Creating Keywords on the fly in Excel ................................................................................................................... 52
Data driven testing .................................................................................................................................................. 53
Sahi Flex Support- sfl (Beta) ....................................................................................................................................................... 54
Introduction ............................................................................................................................................................. 54
Compile with sfl.swc using command line .............................................................................................................. 54
Compile using Adobe Flash Builder (Add SWC files to Flex Builder projects) ..................................................... 54
Recording a flex application .................................................................................................................................... 55
Load Testing with Sahi Pro (Beta) .......................................................................................................................................... 56
Concept ................................................................................................................................................................... 56
Instructions: ............................................................................................................................................................. 56
Appendix 1: Configure Sahi from the Dashboard.............................................................................................................. 57
Appendix 2: APIs ............................................................................................................................................................................... 58
Browser Accessor APIs : ......................................................................................................................................... 58
Identifiers ............................................................................................................................................ 58
DOM relations ..................................................................................................................................... 59
Positional Relations ............................................................................................................................. 60
Accessors of HTML Elements: ............................................................................................................. 61
Accessors of Table related elements .................................................................................................. 65
Accessors of Form elements ............................................................................................................... 66
Accessors of HTML5 Form elements................................................................................................... 68
Accessors of parent DOM Nodes ........................................................................................................ 70
Accessors of IFrames and Rich Text Editors based on IFrames in editable mode .............................. 71
Generic accessors ............................................................................................................................... 72
Browser popups: Alerts, Confirms and Prompts................................................................................ 73
Utility functions to access properties of elements ............................................................................. 74
Marker functions to show DOM relation ............................................................................................ 77


Sahi Pro Tyto Software Pvt. Ltd. 5

Marker functions to show Positional relation .................................................................................... 77
Browser Action APIs .............................................................................................................................................. 79
Mouse Actions .................................................................................................................................... 79
Focus Actions ...................................................................................................................................... 84
Key Actions .......................................................................................................................................... 85
Data Input Actions .............................................................................................................................. 86
Assertions ............................................................................................................................................ 89
Utility actions ...................................................................................................................................... 93
Actions to mock out particular URLs ................................................................................................ 100
Actions to set expectations for javascript confirms and prompts .................................................... 102
Actions used for debugging .............................................................................................................. 103
Toggle KeepAlive Actions .................................................................................................................. 105
Cookie related actions ...................................................................................................................... 105
Download related actions ................................................................................................................. 106
Miscellaneous APIs ............................................................................................................................................... 109
Functions available on browser and on proxy .................................................................................. 109
Functions available on proxy only .................................................................................................... 112
Recovery functions ........................................................................................................................... 114
Working with databases ................................................................................................................... 118
Working with files ............................................................................................................................. 121
Data driven testing ............................................................................................................................ 123
APIs for browser detection ............................................................................................................... 125
APIs for screen capture ..................................................................................................................... 125
Appendix 3: Integrate with Jenkins ..................................................................................................................................... 127
Appendix 3: Configuring Sahi with Xvfb............................................................................................................................ 130
What is xvfb? ........................................................................................................................................................ 130
Installing Xvfb: ..................................................................................................................................................... 130
Setting up Xvfb on display 1: ................................................................................................................................ 131
Running test in Xvfb headless browser through Sahi:........................................................................................... 131
Appendix 4: Reading XML with Sahi .................................................................................................................................... 132


Sahi Pro Tyto Software Pvt. Ltd. 6

Appendix 5: Troubleshooting Sahi Pro ............................................................................................................................... 133
My Dashboard does not show all installed browsers: ........................................................................................... 133
I am unable to access HTTPS/SSL sites on IE. ..................................................................................................... 134
My AJAX pages do not render correctly when navigating through Sahi, or I get Javascript errors only when going
through Sahi. ......................................................................................................................................................... 138
Controller does not identify elements on one website. It works for other websites. ............................................. 139
Playback starts but keeps waiting on some page ................................................................................................... 139
Connecting through VPNs for IE .......................................................................................................................... 139
Appendix 6: Sahi headless execution with PhantomJS ................................................................................................ 140
Quick start guide for using PhantomJS with Sahi Pro for load testing: ................................................................. 140
Normal Installation: ............................................................................................................................................... 140




Sahi Pro Tyto Software Pvt. Ltd. 7

Sahi - Introduction

Sahi is an automation tool to test web applications. Sahi injects javascript into web pages using a proxy
and the javascript helps automate web applications.
Sahi is a tester friendly tool. It abstracts out most difficulties that testers face while automating web
applications. Some salient features include:
Excellent recorder
Platform and browser independence
No XPaths
No waits
Multithreaded (parallel) playback
Excellent Java interaction
Inbuilt reporting
Sahi Pro builds on Sahi Open Source to add significant time saving features. Sahi Pro adds the ability to:
Spread playback across multiple machines
Edit scripts and create functions right from the Controller
Build object repositories automatically while recording
Automatically accept SSL certificates
Automate your flex components with sfl - Sahi Flex (Beta)
Compare logs and screenshots to compare the outcomes of scripts run on different browsers
Customize your logs as XML, HTML or directly feed them to a database. Modify XSL style sheets
to get custom reporting according to your needs.
Use inbuilt Excel based Framework which lets non-technical users participate in automation




Sahi Pro Tyto Software Pvt. Ltd. 8

Sahi Architecture

Sahi uses a HTTP proxy at its core to inject javascript into web pages. The injected Javascript uses
custom code to identify elements on the browser and simulate actions like click, type etc. on them.

Html responses which pass through the proxy are modified such that JavaScript is injected at the start
and the end of the response. This allows the browser to record and playback scripts and talk back to the
proxy when needed. Apart from handling requests for pages that the browser requests, Sahis proxy also
handles custom commands related to recording, playback etc. which the browser sends.
The architecture of Sahi allows Sahi to be used on any browser or operating system. Sahi relies on two
core technologies/concepts:
HTTP proxy to inject code
Javascript code to find elements and emulate actions
Both these technologies are basic building blocks of internet technologies and will necessarily be
supported by all browsers, making Sahi very easily extensible to newer browsers or newer versions of
browsers.



Sahi Pro Tyto Software Pvt. Ltd. 9

Sahi Advantages

Sahi is an engineering solution for an engineering problem. We use heuristics based algorithms, fuzzy
logic, thresholds etc. to arrive at a solution which is 99.9% correct. Sahi also exposes the ability to be
exact when needed, making Sahi very suitable for any web application.
Browser Platform Independence
Sahi, because of its architecture, supports any browser with javascript support and any Operating
System with Java support
Smart Identification Mechanisms
The Javascript DOM exposes a lot of properties of various elements on the browser. Sahi uses these
different properties to identify elements. One significant point is that Sahi gives the visible text a higher
priority than other code related properties like css style. This helps in two ways
Writing and maintaining test scripts become very easy. What you see is what you script.
It validates what a user sees and not what a developer coded.
Sahi automatically goes through frames, iframes etc. to find elements. One does not need to explicitly
select a frame in the automation script. So if developers moved the login fields into an iframe, Sahi will
still work with your older scripts.
UI Relations
Sahi is slightly different from other automation technologies. It relies less on the underlying code and
more on the business intention of the user interface. Code changes are frequent in an evolving
application and relying on business intention is a more stable way of writing automation test cases. Sahi
does this through what is called UI Relations. UI Relations help identify one element with respect to
another element which communicates strong business intention.
For example:
The cost of "Laptop" in a tabular structure may be represented in Sahi as
_cell(0, _near(_div("Laptop")), _under(_div("Cost")))
This represents the cell which is near "Laptop" and under "Cost". Note that even if there are more
columns or rows added in that grid structure, this always points to the correct cell. If we had used the
column index or row index, the test would break as soon as the location of Laptop or Cost changed.
Parallel Playback
Sahi allows Parallel or Multithreaded playback. Multiple tests can be run simultaneously to reduce
playback time, thus reducing your build time and shortening your feedback cycle. One can also spread
the tests across machines or on the cloud and get one consolidated report, all stored in a database.



Sahi Pro Tyto Software Pvt. Ltd. 10

Getting Started
Prerequisites
Java 1.5 or above is needed for running Sahi.
Download Sahi Pro
Download Sahi Pro from http://sahi.co.in/w/download-sahi-pro

Installation of Sahi
Once Sahi Pro is downloaded, double click on the jar file to run the installer.
If that does not work, navigate to the folder on command prompt and run
java -jar install_sahi_pro_v36_yyyymmdd.jar
On starting the installer, follow the steps below:




Sahi Pro Tyto Software Pvt. Ltd. 11





Sahi Pro Tyto Software Pvt. Ltd. 12






It is recommended
to install Sahi on a
folder without
spaces in the path


Sahi Pro Tyto Software Pvt. Ltd. 13







Sahi Pro Tyto Software Pvt. Ltd. 14






Sahi Pro Tyto Software Pvt. Ltd. 15

Starting Sahi

Start Sahi Dashboard by any of the following methods:
1) Double click on the desktop shortcut
2) Go to Start -> All Programs -> Sahi -> Start Sahi
3) Start from the command line.
Windows: Go to <SahiPro>\userdata\bin and run start_dashboard.bat
Linux Go to <SahiPro>/userdata/bin and run start_dashboard.sh
The Sahi Dashboard starts the Sahi proxy, and allows launching of different browsers. Sahi automatically
modifies the browsers proxy settings, so that requests go through the Sahi Proxy (localhost:9999)





If the browsers are not visible on Dashboard, look here for trouble shooting:
http://sahi.co.in/w/trouble-shooting-sahi
Sahi
Configuration
Opens the
Scripts folder in
a file explorer
Root certificate
importer
HTML based
results stored in
database

Opens a terminal at
userdata/bin folder
Turn On (Off)
HTTP Traffic
Logging



Sahi Pro Tyto Software Pvt. Ltd. 16

Recording through Sahi

Click on any browser on the Dashboard. A browser window should open with the following
screen




Sahi Pro Tyto Software Pvt. Ltd. 17


Press ALT and double click on the window which you want to record. The Sahi Controller will
pop up. (If that does not work, press CTRL and ALT keys together and then double click. Make
sure popup blockers are turned off)





Sahi Pro Tyto Software Pvt. Ltd. 18

On the controller, go to the Record tab.
Give a name for the script, and click Record. (.sah is optional)


Navigate on your website like you normally would. Most actions on the page will now get
recorded.
o The currently recorded step is visible in the Evaluate Expression box


o All recorded steps are visible in the Recorded Steps box




Sahi Pro Tyto Software Pvt. Ltd. 19

Add an assertion:
o Move the mouse over any html element while pressing Ctrl key. The Accessor field will
get populated in the controller.

o Click the Assert button to generate assertions for the element. They will appear in the
Evaluate Expression box.
o Click Test > to check that the assertions are true. You can evaluate any javascript
using Evaluate Expression and Test >. Actions performed via the controller will not
be automatically recorded. Only actions performed directly on the page are
automatically recorded. This lets you experiment on the webpage at recording time
without impacting the script.
o Once satisfied, click on Append to Script. This will add the assertions to the script.

Click Stop to finish recording.
Press CTRL
key and
Hover
mouse


Sahi Pro Tyto Software Pvt. Ltd. 20

Note that the controller can be closed and reopened at any time, without disrupting recording.
The recorded script is stored in <sahi_pro>\userdata\scripts directory. The recorded script can be
viewed and edited easily through any text editor. Sahi Scripts are simple text files which use Javascript
syntax.
The script can be edited even while recording, so that logical segregation into functions etc. can be done
as recording happens.



Sahi Pro Tyto Software Pvt. Ltd. 21

Playing back through Sahi
Running a test from the controller
Open the Sahi controller (ALT-Dbl click on the page).
Click on Playback tab
Enter the script name in the File: field (with the help of the auto completion feature)
Enter the start URL of the test. Eg. If you had started recording from
http://sahi.co.in/demo/training/, use that URL.
Click Set.
Wait for the page to reload.
Click Play.
Steps will start executing, and the controller will be updated accordingly. Once finished, SUCCESS or
FAILURE will be displayed at the end of the steps.

Note that the controller can be closed at any time, without disrupting playback.



Sahi Pro Tyto Software Pvt. Ltd. 22

View Logs
On the controller, go to Playback tab and click on View Logs link at the bottom right. It will open a
window with the results neatly formatted in HTML.
Clicking on a line in the logs will drill down to exact line in script. Logs show all the assertion in green. If
the assertion has failed it will show in red. You can click on any of these lines to go into the line of script
to debug. You can also view the logs at http://localhost:9999//_s_/dyn/pro/DBReports



Clicking on the error takes you
to the correct line in script


Sahi Pro Tyto Software Pvt. Ltd. 23

Creating a Suite File
Multiple scripts can be run in a batch using suites. A suite file is a normal text file with an extension of
.suite. It includes all the Sahi scripts that need to be executed as a batch

Suites can be run from a command prompt or through ant. They cannot be run from the Controller.
Suite logs show details of all scripts run



Sahi Pro Tyto Software Pvt. Ltd. 24

Running a test or suite from command line
The following command is used to run a test from a command line.
Command:

Eg.


cd sahi/userdata/bin
testrunner.bat demo/demo.suite http://sahi.co.in/demo/ firefox
testrunner.bat demo/sahi_demo.sah http://sahi.co.in/demo/ ie


One can directly click on the Bin link on the Dashboard to open a command prompt at usedata/bin
NOTE: Example scripts and suites can be found in SAHI_HOME/userdata/scripts/demo folder






testrunner.bat <sah file|suite file> <startURL> <browserType> <tags>



Sahi Pro Tyto Software Pvt. Ltd. 25

Running a test or suite using ant:

Sahi tests and suites can be invoked from ant. Below is a snippet to run demo.suite through ant. The
paths and classpaths may need to be adjusted depending on where you call your ant file from.

<taskdef name="sahi" classname="net.sf.sahi.ant.RunSahiTask" classpath="lib/ant-sahi.jar"/>
<target name="failsahi" if="sahi.failed">
<fail message="Sahi tests failed!"/>
</target>
<target name="runbrowsertests">
<sahi suite="../userdata/scripts/demo/demo.suite"
browserType="firefox"
baseurl="http://machine_name/path/"
sahihost="localhost"
sahiport="9999"
failureproperty="sahi.failed"
haltonfailure="false"
threads="6">
<report type="html"/>
<report type="junit" logdir="../userdata/temp/junit"/>
</sahi>
<antcall target="failsahi"/>
</target>


This can be invoked as ant browsertests.
Parameters (sahi)
Attribute Description Required
suite path to suite or test file Yes
browserType The name of the browserType as specified in browser_types.xml Yes
baseurl url relative to which all urls to be tested will be resolved Yes
sahihost IP or hostname of server where Sahi is running Yes
sahiport port where Sahi is running Yes
failureproperty Name of property which will be set to false in case build fails. Yes
haltonfailure Takes "true" or "false". Specifies if build should stop executing other tests if
one test fails.
Yes
singlesession Takes "true" or "false". If true, all scripts run sequentially in a single
browser session without closing the browser. threads is ignored.
No
threads Number of simultaneous browser instances where sahi tests will be run.
Works for IE, Firefox and Chrome
No

Nested Elements
report Specifies type and location of report types can be junit html tm6 No



Sahi Pro Tyto Software Pvt. Ltd. 26

Distributing tests across different machines using ant:
Use this code snippet to distribute tests across different machines.
<taskdef name="sahid" classname="in.co.sahi.ant.DAntRunner" classpath="lib/ant-sahi.jar"/>
<target name="failsahi" if="sahi.failed">
<fail message="Sahi tests failed!"/>
</target>
<target name="drun">
<tstamp>
<format property="ts" pattern="yyyy_MM_dd_HH_mm_ss" locale="en, IN"/>
</tstamp>
<property name="tempdest" value="temp/scripts/${ts}"/>
<sahid suite="${tempdest}/demo/demo.suite"
baseurl="http://${urlbase}/demo/"
sahihost="localhost"
sahiport="9999"
failureproperty="sahi.failed"
haltonfailure="false"
browserType="firefox">
<sync originFolder="userdata/scripts" destFolder="${tempdest}" ignorePattern=".*(svn|copied).*"/>
<node host="localhost" port="9999"/>
<node host="othermachine" port="9999"/>
</sahid>
<antcall target="failsahi"/>
</target>

Parameters (sahid)
Attribute Description Required
suite path to suite or test file Yes
browserType The name of the browserType as specified in browser_types.xml Yes
baseurl url relative to which all urls to be tested will be resolved Yes
sahihost IP or hostname of server where Sahi is running Yes
sahiport port where Sahi is running Yes
failureproperty Name of property which will be set to false in case build fails. Yes
haltonfailure Takes "true" or "false". Specifies if build should stop executing other tests if
one test fails.
Yes

Additionally, the user will have to specify the machines on which the tests have to be distributed.
Specify them in the nested node tag.
Parameters (node)
Attribute Description Required
host Name or IP Address of the machine Yes
port Port where Sahi is running on the remote machine Yes

For the tests to be distributed across remote machines, the user will also need to make sure that the
scripts are available in each of those machines. This is taken care of by the nested sync tag.


Sahi Pro Tyto Software Pvt. Ltd. 27

Parameters (sync)
Attribute Description Required
originFolder Scripts folder to copy over Yes
destFolder Folder which will contain the scripts after copy Yes
ignorePattern Any files with a specific pattern that need to be ignored No

Load testing using ant:
This code snippet can be used to perform load testing. (Read more about load testing with Sahi here)
<taskdef name="sahiload" classname="in.co.sahi.ant.DAntLoadRunner" classpath="lib/ant-sahi.jar"/>
<target name="failsahi" if="sahi.failed">
<fail message="Sahi tests failed!"/>
</target>
<target name="dloadrun">
<tstamp>
<format property="ts" pattern="yyyy_MM_dd_HH_mm_ss" locale="en, IN"/>
</tstamp>
<property name="tempdest" value="temp/scripts/${ts}"/>
<sahiload subject="${tempdest}/demo/load/subject.sah"
baseurl="http://${urlbase}/demo/training/"
sahihost="localhost"
sahiport="9999"
failureproperty="sahi.failed"
haltonfailure="false"
browserType="firefox"
noise="${tempdest}/demo/load/noise.sah"
noiseBrowserType="phantomjs"
min="1"
max="5"
incrementBy="2"
interval="5">
<sync originFolder="userdata/scripts" destFolder="${tempdest}" ignorePattern=".*(svn|copied).*"/>
<node host="localhost" port="9999"/>
<node host="othermachine" port="9999"/>
</sahiload>
<antcall target="failsahi"/>
</target>



Sahi Pro Tyto Software Pvt. Ltd. 28

Parameters (sahiload)
Attribute Description Required
subject Path to script whose steps need to be measured periodically at different
loads.
Yes
browserType The name of the browserType as specified in browser_types.xml Yes
baseurl url relative to which all urls to be tested will be resolved Yes
sahihost IP or hostname of server where Sahi is running Yes
sahiport port where Sahi is running Yes
failureproperty Name of property which will be set to false in case build fails. Yes
haltonfailure Takes "true" or "false". Specifies if build should stop executing other
tests if one test fails.
Yes
noise Script to generate the load Yes
noiseBrowserType Browser to run the noise on (Ideally, use a headless browser like
phantomjs)
Yes
min Minimum number of threads to run the noise Yes
interval Time (in seconds) to wait before incrementing the load Yes
incrementBy Number of threads to increase after an interval Yes
max Maximum number of threads to run the noise Yes

It is also possible to involve multiple machines in creating the load by specifying the machine names in
the node tag.
Note: Sample examples are shipped with Sahi Pro and are available in sahis root folder in demo.xml



Sahi Pro Tyto Software Pvt. Ltd. 29

Sahi Pro Controller
Recorder Tab




Sahi Pro Tyto Software Pvt. Ltd. 30

The Anchor Button
The Anchor button on the Recorder helps in identifying one element relative to another.
Usage:
1. CTRL - Mouse over Element1 on browser
2. Click the Anchor button
3. CTRL - Mouse over Element2 on browser.
4. Element2 will be resolved relative to Element1
Example
Suppose we need to identify the third textbox in the UI below

If we hover over the third textbox, it is identified as _textbox(q[2])
Instead, we first CTRL-Hover over Python Cookbook; the Accessor field shows:

Then we click the Anchor button

Now if we CTRL-Hover over the textbox, we see that the Accessor now resolves the textbox in relation
with Python Cookbook.




Sahi Pro Tyto Software Pvt. Ltd. 31

Using the Sahi Script Editor
The Sahi script Editor is used to edit and Refactor Sahi scripts after recording. It allows conversion of
steps into parameterized functions and extraction of constants.


Select the steps you want to convert to a function and click Create Function.
The Right hand panel will extract function parameters.
Specify a function name, and choose the required parameters and constants.
Click on Continue to create function code. If not satisfied, Click Undo to revert.


Sahi Pro Tyto Software Pvt. Ltd. 32


Save the script once done.













Sahi Pro Tyto Software Pvt. Ltd. 33

Playback Tab








Enter the script
name
Enter the start
URL of the script
Set the script for
playback
Recorder Tab
Playback Tab
Click to play the
script
Click for browser,
OS and java related
information
View played
back steps and
status
A copy of the test
script currently
loaded for play back
is displayed in the
web browser.
Displays the actual
code that will be
executed by Sahi
The browser
scripts included in
the Sahi script
Click to step
through the script,
one step at a time
Click to stop the
script
Resets the script
to play from 0
Click to pause the
script
Next step to
execute. Changing
this value, will
cause Sahi to skip
steps till this.
HTML based
results of tests


Sahi Pro Tyto Software Pvt. Ltd. 34

Running Tests on multiple machines
Sahi can distribute and run tests on multiple machines (nodes)
Configuration:
1) Sahi needs to be running on each machine
2) Browser paths need to be correctly specified in browser_types.xml on each node.
Refer http://sahi.co.in/w/browser-types-xml for more details on how to configure browser_types.xml
Once Sahi is started on all nodes, a suite can be run using this ant target:

<taskdef name="sahid"
classname="in.co.sahi.ant.DAntRunner"
classpath="lib/ant-sahi.jar" />
<target name="drun">
<tstamp>
<format property="ts" pattern="yyyy_MM_dd_HH_mm_ss" locale="en, IN" />
</tstamp>
<property name="tempdest" value="scritps/${ts}" />
<sahid suite="${tempdest}/demo/demo.suite"
baseurl="http://${urlbase}/demo/"
sahihost="localhost"
sahiport="9999"
failureproperty="sahi.failed"
haltonfailure="false"
browserType="firefox">
<sync originFolder="userdata/scripts" destFolder="${tempdest}"
ignorePattern=".*(svn|copied).*" />
<node host="localhost" port="9999" />
<node host="machine1" port="9999" />
<node host="machine2" port="9999" />
</sahid>
<antcall target="failsahi" />
</target>


sahid task which can distribute tests across multiple machines.
<sync> copies the originFolder to destFolder. destFolder will be created in sahi_pro/userdata directory
on every node. In this target we are dynamically creating a directory every time, based on the
timestamp.
<node> The nodes have to be specified using <node> tags.
browserType specifies the type of browser to pick. This maps to the <name> attribute in
browser_types.xml
NOTE: Refer to userdata/bin/drun.bat and drun.sh for running from command line


Sahi Pro Tyto Software Pvt. Ltd. 35

Reports
All reports are logged into the database by default. They can also be logged into the filesystem based on
settings in sahi.properties or userdata.properties

reports.filesystem.html.enabled=true
reports.filesystem.xml.enabled=true
reports.db.enabled=true
reports.sql.enabled=true

# Database logging.
# Tables are created using sahi/user data/config/db/create_report_tables.sql
db.driver_name=org.h2.Driver
db.jdbc_url=jdbc:h2:$userDir/database/db0;DB_CLOSE_DELAY=-1
db.user_name=sa
db.password=
db.script_gen_xsl=$userDir/config/db/script_sql_gen.xsl


Reports can be accessed at http://localhost:9999/_s_/dyn/pro/DBReports
This URL is available as a link at the bottom of Playback tab.





Sahi Pro Tyto Software Pvt. Ltd. 36

Database Report






Sahi Pro Tyto Software Pvt. Ltd. 37

Suite Report

Script Report



Sahi Pro Tyto Software Pvt. Ltd. 38

Log comparison (via Compare Logs link)


HTML, SQL and XML logs are created in a time-stamped folder under
sahi_pro/userdata/logs/playback/<suiteLogFileName>

HTML logging converts result XML to HTML using XSL files in sahi_pro/userdata/config/reports.
Database logging is done by first converting XML to SQL using XSL files in sahi_pro/userdata/config/db
and then firing those queries against the database configured in sahi.properties or userdata.properties.
Database tables are created if required using sahi_pro/userdata/config/db/create_report_tables.sql
Sahi Pro is bundled with H2, a filesystem based small database. The database files are in
sahi_pro/userdata/database. The files db0.h2.db, db0.trace.db and db0.lock.db can be deleted to
recreate logs from scratch.


Sahi Pro Tyto Software Pvt. Ltd. 39

Sahi Scripting Basics
Sahi script is based on javascript, but they are not the same. Sahi script is parsed by the proxy and the
parsed script is fully valid javascript which is executed by the rhino javascript engine. Below are the
normal constructs used in Sahi script. They are the same as javascript except for the mandatory $ used
in variables.
Statements:
Statements are normal lines of code. They end with a semi-colon.
For example,
_click(_link("Login"));
Variable declaration:
Syntax var $variableName = value;
or
var $variableName; // declaration
$variableName = value; // assignment
Example var $username = "SahiTestUser";
var $password; // declaration;
$password = $username + "_password"; // "SahiTestUser_password"
Note All variables start with a $. The keyword var is used for local variables.
Function declaration:
Syntax function functionName($parameter1, $parameter2) {
// statements
}
Example //function declaration
function login($usr, $pwd){
_click(_link("Login"));
_setValue(_textbox("username"), $usr);
_setValue(_password("password"), $pwd);
_click(_submit("Login"));
}
//function call
login("sahi_user", "secret");
Comments:
// This is a single line comment

/*
This is a multiline comment.
This has two lines
*/


Sahi Pro Tyto Software Pvt. Ltd. 40

if statements:
Syntax if (condition) {
// statements
}
Example if ($username == "PartnerUser"){
_click(_link("Partner Login"));
}
If the if condition is page dependent, use
if (_condition(booleanExpression))
For example,
if (document.loginForm.userName =="karthik"){...}
should be written as
if (_condition(document.loginForm.userName == "karthik")){...}
NOTE _condition need not be added if the condition does not depend on any pages DOM.
for loops:
Syntax for (var $i=0; $i<$max; $i++){
// statements
}
Example // This loop will login with user1, password1, user2, password2 etc.
// login and logout are custom functions.
for (var $i=0; $i<10; $i++){
login("user"+$i, "password"+$i);
logout();
}
Note Do not use a condition which depends on a pages DOM.
for (var $i=0; $i<document.links.length; $i++) {...} //WRONG
If you want to iterate over page DOM variable, first take a snapshot of it using _set,
and then use the variable.
For example,
<browser>
var $anchors = [];
function getLinkIds(){
var retVal = [];
var links = document.links;
for (var i=0; i<links.length; i++){
retVal[i] = links[i].innerHTML;
}
return retVal;
}
</browser>
_set ($anchors, getLinkIds());
for (var $i=0; $i<$anchors.length; $i++) {...} //RIGHT


Sahi Pro Tyto Software Pvt. Ltd. 41

while loops:
Syntax while (condition) {
// statements
}
Example $i = 0;
while ($i++ < 10) {
login("user"+$i, "password"+$i);
logout();
}
If the while loop condition is page dependent, use
while (_condition(booleanExpression)){...}
For example,
while (document.loginForm.userName != "karthik"){
// some statements
}
should be written as
while (_condition(document.loginForm.userName != "karthik")){
// some statements
}
Note You do not need to add _condition if the condition is not dependent an the page
DOM.

Including another Sahi script file:
Use _include to include another Script file.
For example,
_include("includes/common_functions.sah");









Sahi Pro Tyto Software Pvt. Ltd. 42

Advanced Scripting
While Sahi scripts can easily be recorded, as a project grows in size, the scripts may have to be more
logically organized into functions and split into multiple files. The following section gives more details on
the Sahi Script and the rules to follow. Sahi script is based on Javascript. The constructs of javascript, like
functions, variables, loops, conditional statements etc. are all available in Sahi script. But the script is
parsed and transformed slightly in the Sahi proxy server before execution.
To keep matters simple, follow these rules.
Perform all actions using Browser Action APIs.
For example,
Use _click(_link("Click Me")) instead of _link("Click Me").click()
Use _setValue(_textbox("tb"), "value") instead of _textbox("tb").value = "value"
Use _set to store a variable with data from browser
var $email1 = null;
_set($email1, _textbox("email1").value);
if ($email1 == "a@sahi.example.com"){
_setValue(_password("pwd"), "secret");
}
Using custom functions that access the DOM.
Custom functions which access the browsers DOM to say, identify a particular element, need to be
wrapped in a <browser></browser> tag.
For example,
<browser>
function getEmailValue(){
return _textbox("email").value;
}
</browser>
_assertEqual("a@sahi.example.com", getEmailValue());

A general tip is to always call a browser based function from inside a Browser Action API. Otherwise they
will be executed on the proxy and will fail because they do not have access to the browsers DOM.
Prefix a $ sign before variables which are passed to sahi functions.
var $name = "karthik";
_setValue(_textbox("userName"), $name);
Note that $names value karthik is independent of any page.




Sahi Pro Tyto Software Pvt. Ltd. 43

Exception Handling using try-catch
Exceptions are handled via regular javascript try catch blocks
Syntax:
try{
// sahi statements
}catch(e){
// Corrective action
// Can print exact source of error in log
// Can throw the same or another exception
}

For example,
Corrective Action:
try{
_click(_link("does not exist"));
}catch(e){
_log("Exception occured"); // simple logging. no failure
_click(_link("linkByHtml")); // Corrective action
}

Corrective Action and Log the Exception Message:
try{
_click(_link("does not exist"));
}catch(e){
_click(_link("linkByHtml")); // Corrective action
_logException(e); // Logs the exception, but does not fail
}

Corrective Action, Log and then Fail :
try{
_click(_link("does not exist"));
}catch(e){
_click(_link("linkByHtml")); // Corrective action
_logExceptionAsFailure(e); // Logs the exception, and fails,
// and in the logs, points to the original line as source of failure.
}



Sahi Pro Tyto Software Pvt. Ltd. 44

Recovering without try-catch using _setRecovery
Sometimes it is necessary to do some corrective action in case a test fails half way through.
This is different from try-catch because we do not want the script to continue; we just want the state of
our system to be restored to a sensible point.
The relevant APIs are:
1. _setRecovery(fn)
2. _removeRecovery()
Any function can be assigned to a script as a recovery function.
Once set, if there is an error during execution, the recovery function will be called before the script
stops.

The recovery function can be removed via _removeRecovery();
Also refer: Recovery functions
For example,
_navigateTo("http://sahi.co.in/demo/");
function myRecoveryFn(){
_alert("In myRecoveryFn."); // This statement will be alerted in case of script error.
}
_setRecovery(myRecoveryFn); // Set the myRecoveryFn as recovery function.
_click(_link("Link Test")); // Works normally
_click(_link("Bad Link")); // This statement fails and causes myRecoveryFn to be called.
_alert("done"); // This statement will not be called, because script failed in the last statement.


Sahi Pro Tyto Software Pvt. Ltd. 45

Script Lifecycle Call Back Functions
Sahi provides a few hooks or callback functions which are automatically executed at various points of
the script life cycle. These functions need to be defined at the start of the script.
The various functions are:
Function onScriptFailure()
Notes Is called whenever an assertion failure occurs in the script.

Function onScriptError()
Notes Is called whenever an error occurs in the script.

Function onScriptEnd()
Notes Is called at the end of a script (even if there are errors in the script and the script
stops in the middle).

For example,
function onScriptEnd(){
_click(_button("Logout"));
}
function onScriptError(){
_alert(">> In onScriptError");
}
function onScriptFailure(){
_alert(">> In onScriptFailure");
}

_navigateTo("http://sahi.co.in/demo/training/");
_setValue(_textbox("user"), "test");
_setValue(_password("password"), "secret");
_click(_submit("Login"));




Sahi Pro Tyto Software Pvt. Ltd. 46

Sahi Pro Excel Framework

Sahi Pro introduces an advanced way of automation via its Excel Framework. The Sahi Excel Framework
allows testers to write their test cases in Excel and run it from Sahi. Often a testing team consists of a
mix of subject matter experts, some manual testers and testers with some automation experience.
Writing tests in the language of the business allows all stake holders to participate and derive value out
of the automation process.
Sample Excel Sheet
For example, a simple test written as an Excel sheet looks like this:
TestCase Key Word Argument1 Argument2 Argument3
loadSahi "books_lib.sah"


Check shopping cart total [Documentation] Smoke test for add books
login "test" "secret"
addBooks 3 2 1
verifyTotal 1640
logout


Test login error message [Documentation] Checks Invalid login message
login "test" "bad password"
verifyNotLoggedIn
verifyErrorMessage "Invalid username or password"


These tests talk mostly in the language of the business (also called a Domain Specific Language or DSL
for that business), and hide away all the implementation details of clicking buttons and populating
textboxes.
Loading Sahi script libraries
The implementation details are moved into an included Sahi script, which is linked to this Excel sheet via
the initial
loadSahi "books_lib.sah"
statement.


The code in books_lib.sah is given below:


Sahi Pro Tyto Software Pvt. Ltd. 47

function login($username, $password){
_setValue(_textbox("user"), $username);
_setValue(_password("password"), $password);
_click(_submit("Login"));
}

function addBooks($numJava, $numRuby, $numPython){
_setValue(_textbox("q", _near(_cell("Core Java"))), $numJava);
_setValue(_textbox("q", _near(_cell("Ruby for Rails"))), $numRuby);
_setValue(_textbox("q", _near(_cell("Python Cookbook"))), $numPython);
_click(_button("Add"));
}

function verifyTotal($total){
_assertEqual($total, _textbox("total").value);
}

function logout(){
_click(_button("Logout"));
}

function verifyNotLoggedIn(){
_assertExists(_textbox("user"));
}

function verifyErrorMessage($msg){
_assert(_isVisible(_div("errorMessage")));
_assertEqual($msg, _getText(_div("errorMessage")));
}

Executing the Excel Sheet
Executing the Excel sheet is no different from executing a Sahi script.
Just copy the Excel sheet into sahi/userdata/scripts directory (or inside a sub-directory) and the xls file
will be visible in the drop down in Controller Playback tab.
Choose the file, Click "Set" and then "Play" to playback.
Play back reports/logs
On execution, Sahi generates logs showing success or failure. Logs are visible from the "Logs" link in
Playback tab.
Logs can also be accessed via http://sahi.example.com/_s_/dyn/pro/DBReports

A sample log is shown below. Clicking any step expands to show the underlying Sahi steps. You can click
on the log statements below.



Sahi Pro Tyto Software Pvt. Ltd. 48

Starting script
Expand All | Collapse All

loadSahi "sample_lib.sah"

Check shopping cart total [Documentation] Smoke test for add books


login "test" "secret"


addBooks 3 2 1


verifyTotal 1640


logout

Test login error message [Documentation] Checks Invalid login message


login "test" "bad password"


verifyNotLoggedIn


verifyErrorMessage "Invalid username or password"

Stopping script




Please refer to sahi/userdata/scripts/demo/framework folder for some examples.
IMPORTANT NOTES
1. You may need to close the Excel sheet before running it
2. Only the first sheet will be executed. The first sheet should be called Sheet1 and should not be
renamed
3. MS Excel needs to be installed on the system
4. Due to a bug, numbers need to be formatted as text in Excel. One can do this by entering a
single quote before entering the number
For example type '23 instead of 23.




Sahi Pro Tyto Software Pvt. Ltd. 49

Syntax
Test
Case
Key word Argument 1 Argument
2
Argument
3
Very first line of sheet
Blank lines are ignored
loadSahi "custom_lib.sah" Loads a Sahi script with
required function definitions

Test
Case
One
Step One Param1 Param2 New test case started.
StepOne(Param1, Param2) is
called.
Step Two Param3 StepTwo(Param3) is called

Test
Case
Two
Step One 25 "age" New test case started.
String values are quoted
Step Two Param5

Test
Case
Three
[Documentation] Some
description
about the test
case
[Documentation] is useful for,
well, documentation
Step One 25 "age" New test case started.
String values are quoted
// Step Two Param5 Commented step using //
Step Two Param6


Spaces will be removed from keywords and corresponding functions invoked. The rules for writing the
Excel sheet are as follows

The first line should be populated with
Test Case | Key word | Argument 1 | Argument 2 | Argument 3
The names of the columns are not important, but they should not be left blank
If the first column is populated, a new test case is started.
The second column holds keywords. Keywords are mapped to functions in the included Sahi script.
They can be user defined functions or Sahi APIs themselves




Sahi Pro Tyto Software Pvt. Ltd. 50

For example,
login "test" "secret"
in the excel sheet, maps to the javascript call
login("test", "secret");
_assertEqual _getText(_cell("msg")) "abcd"
becomes
_assertEqual(_getText(_cell("msg")), "abcd");
Variables
The Excel framework also supports variables, eg.
$userId=createUserInGroup "My name" "My group"
verifyUserCreated $userId "My name" "My group"

or
$msg= _getText(_cell("msg"))
_assertEqual $msg "abcd"
SetUp and TearDown
Different test cases may need the same steps to be executed before and after.
For example, one may need to login before and logout after each test case.
This can be accomplished through global SetUp and TearDown blocks.
TearDown will be called inspite of any errors or failures in the testcase.

[Global] [SetUp]
_log "In Global Setup"
login "test" "secret"

[TearDown]
_click _button("Logout")
_log "In Global Teardown"

Verify books total addBooks 3 2 1
verifyTotal 1650

Verify books again addBooks 3 2 2
verifyTotal 2000

This will execute as:


Sahi Pro Tyto Software Pvt. Ltd. 51

_log "In Global Setup"
login "test" "secret"
addBooks 3 2 1
verifyTotal 1650
_click _button("Logout")
_log "In Global Teardown"


_log "In Global Setup"
login "test" "secret"
addBooks 3 2 2
verifyTotal 2000
_click _button("Logout")
_log "In Global Teardown"





Sahi Pro Tyto Software Pvt. Ltd. 52

Creating Keywords on the fly in Excel
Keywords are normally created as functions in the included Sahi scripts, so that the details are hidden
away and one gets good programmatic control in the scripts.
But sometimes it may be convenient to club together different steps and create a keyword in the Excel
sheet itself.

Create
AddBooksCheck
Key Word
[CreateKeyword] Add
Books
Check
[CreateKeyword] command
creates a keyword called
"Add Books Check"
[Arguments] $java $ruby $python $total These are the arguments or
parameters that "Add Books
Check" takes as input
[Documentation] Data
drivable
add
books
check

addBooks $java $ruby $python
verifyTotal $total


So now, a call to "Add Books Check" like this:
Add Books Check 3 2 1 1650


is equivalent to
addBooks 3 2 1
verifyTotal 1650




Sahi Pro Tyto Software Pvt. Ltd. 53

Data driven testing
Data
Driven
Example
[Keyword] Add Books Check Starts a testcase "Data
Drivern Example"
AddBooksCheck function
will be called for the data
set below.

[SetUp] This will be called
BEFORE each row of data
login "test" "secret"

[TearDown] This will be called AFTER
each row of data
_click _button("Logout")

[Documentation] java ruby python total Ignored by Sahi. Makes
test case more readable
[Data] 3 2 1 1650 [Data] denotes start of
data
4 5 0 2100
0 1 9 3350

This roughly translates to:
login "test" "secret"
Add Books Check 3 2 1 1650
_click _button("Logout")

login "test" "secret"
Add Books Check 4 5 0 2100
_click _button("Logout")

login "test" "secret"
Add Books Check 0 1 9 3350
_click _button("Logout")


Please refer to sahi/userdata/scripts/demo/framework folder for some examples.



Sahi Pro Tyto Software Pvt. Ltd. 54

Sahi Flex Support- sfl (Beta)

Introduction
Sahi Pro provides support for automation of flex applications. Before automating your flex application
you will first need to compile your swf with the correct version of sfl.swc
Eg. If your application is compiled with Flex 4.0, use sfl4.swc
Compile with sfl.swc using command line
You can compile your flex application with sfl using the following command (Change sfl version as
needed)
mxmlc yourapp.mxml -include-libraries+=sfl4.swc --output=yourapp.swf
Compile using Adobe Flash Builder (Add SWC files to Flex Builder projects)

In Flex Builder, select your Flex project in the Navigator.
Select Project > Properties. The Properties dialog box appears.
Select Flex Compiler in the tree to the left. The Flex Compiler properties panel appears.
In the "Additional compiler arguments" field, enter the following command:
-include-libraries "sfl4.swc"

In Flex Builder, the entries in the include-libraries compiler option are relative to the Flex Builder
installation directory.
The default location of this directory on Windows is C:\Program Files\Adobe\Flex Builder.
After compilation refresh the browser cache, to make sure that the modified yourapp.swf is available.







Sahi Pro Tyto Software Pvt. Ltd. 55

Recording a flex application


From the dashboard, open any browser and navigate to your flex application.
Press ALT and double click on the window which you want to record. Sahis Controller window will pop
up. You can now start recording your Flex application.

NOTE:
Ctrl + hover (to get a flex elements accessor) will work only if the Flex object is in focus. To do
this, you will have to first click on the Flex object.
Flex APIs are different from the normal JavaScript APIs.
Eg. _f("yuiswf0").textinput("username2")








Sahi Pro Tyto Software Pvt. Ltd. 56

Load Testing with Sahi Pro (Beta)

Concept
Sahi Pro lets you run load tests on your application. There are 2 Sahi scripts involved in this. One is used
to generate the load. This script is called the noise and is run on a headless browser. The steps in the
noise file are generally in an infinite loop so that they never terminate. The other script is called the
subject. The subject is the script whose steps you would like to measure periodically at different loads.
Instructions:
1. Get the headless browser: PhantomJS
Read this article to add PhantomJS to Sahi.
2. Start Sahi Pro. PhantomJS should be visible on the Dashboard as one of the browsers.
3. On the dashboard, click on the "Bin" link. This will open up a command prompt at userdata/bin
4. On the command prompt, run
dload.bat demo/load/noise.sah demo/load/subject.sah http://sahi.co.in/demo/training firefox
This will do the following:
1. Run 1 (min) threads of noise.sah on PhantomJS (This will not be visible)
2. Run subject.sah on firefox browser and store the time of steps.
3. Wait for 5 seconds (interval)
4. Run 2 (incrementby) more threads of noise.sah on PhantomJS
5. Run subject.sah on firefox and store results
6. Keep incrementing the noise threads at periodic intervals, run the subject, and store results, till
it reaches max noise threads.
Once done, click on "Logs" link on the Dashboard to view results.
To test your application, go to userdata/scripts/demo/load folder.
1. Open noise.sah and add your sequence of steps. These steps should be representative of a
normal user interaction. Note that your steps should be in a while(true){} loop so that the
threads don't die out. (Refer to existing noise.sah)
2. Open subject.sah and specify the sequence of steps whose reaction times you would like to
measure at different loads.
The parameters min, max, incrementby, interval etc. can be edited in dload.bat file.
It is also possible to involve multiple machines in creating the load by modifying the "NODES" variable
(Look in dload.bat)





Sahi Pro Tyto Software Pvt. Ltd. 57

Appendix 1: Configure Sahi from the Dashboard

Various attributes of Sahi can be modified from the Dashboard by clicking the Configure link.
browser_types.xml: browser_types.xml configures the various browsers that Sahi can use. Note that
browser options for various browsers are different and it is advisable to use the defaults provided and
only change the paths where needed.
userdata.properties: Sahi can be configured using two files:
sahi/userdata/config/ userdata.properties
sahi/config/sahi.properties
Sahi first looks for a property in userdata.properties, and if not found, looks for it in sahi.properties. It is
recommended to modify/add properties to userdata.properties. Every property in sahi.properties can
be overridden in userdata.properties
Details of different properties are available as comments in sahi.properties
exclude_inject.txt: Sahi controls the browser by injecting javascript into web pages. However there are
various requests like XMLHttpRequests, javascript, css, etc. where Sahi should not inject its code. While
this is correctly detected and handled in most cases, there are instances where one may need to
explicitly ask Sahi not to inject code. In such instances, patterns can be added to exclude_inject.txt.
When a URL matches this pattern, Sahi will NOT inject its code.
download_urls.txt: Sahi automatically downloads and saves files into sahi/usedata/temp/downloads
directory. If Sahi is unable to detect a request as a download, you can force it to download the file by
adding URL patterns to this file.
download_contenttypes.txt: Sahi automatically downloads and saves files into
sahi/usedata/temp/downloads directory. If Sahi is unable to detect a request as a download, you can
force it to download the file by adding relevant content-types to this file.
block_ssl_domains.txt: If a domain is added here, any HTTPS calls to this domain will return a 404 error.
Browsers like firefox make HTTPS requests to addons.mozilla.org and sb-ssl.google.com which can hang
playback. Adding these domains to block_ssl_domains.txt will prevent hangs.
url_history.txt: Sahi stores a history of all URLs entered on Sahi home page in this file.

NOTE: Once changes are made, you will have to click on the Save button and restart Sahi for those
changes to take effect.



Sahi Pro Tyto Software Pvt. Ltd. 58

Appendix 2: APIs
Browser Accessor APIs :
Browser Accessor APIs help access elements on the browser. They need to be executed on the browser
and not in the proxy. They should be used as parameters to Browser Action APIs.
All accessor APIs take an identifier and an optional domRelation.
Identifiers can be a numerical index, a string or regular expression, or an associative array.
Identifiers which are strings can also have an index along with them in square brackets as part of
the string.
Identifiers which are associative arrays can specify various filtering attributes and also an index
Identifiers
Simple case where links are uniquely identifiable:
For example:
<a href="http://sahi.co.in" id="sahi_link">Link to Sahi website</a>

This can be represented in the following ways
_link(12) Using index in a page; assuming this is the 13
th
link on the page
_link("sahi_link") Using id as a string
_link(/.*_link/) Using id as a regular expression
_link("Link to Sahi website") Using visible text as a string
_link(/Link to .* website/) Using visible text as a regular expression
_link("/Link to .* website/") Using visible text as a regular expression
_link({id:"sahi_link"}) Using an associative array with id
_link({sahiText:" /Link to .*/"}) Using an associative array with visible text as regular expression

Case where multiple elements with similar property are present:
For example:
<table>
<tr>
<td>User One</td>
<td id="del1"><a href="/deleteUser?id=1">delete</a></td>
</tr>
<tr>
<td>User Two</td>
<td id="del2"><a href="/deleteUser?id=2">delete</a></td>


Sahi Pro Tyto Software Pvt. Ltd. 59

</tr>
</table>

There are two delete links in this table and there may be more.

_link("delete") points to the first delete link. Same as _link("delete[0]").
_link("delete[1]") points to the second delete link; Note that indexing starts at 0.
_link("/del/[1]") points to the second delete link; Note that indexing starts at 0.
_link({sahiText:"/del/", sahiIndex:1}) same as above.

Using indexes works fine as long as the page is static, but it is not recommended for dynamic
applications, as it makes scripts fail when changes are made to the web pages.
DOM relations
When elements are not uniquely identifiable by themselves, we should try to identify them in relation to
either some element near them or by the element in which they are contained.
_near is a DOM relation marker which specifies that the element should be searched near another
element.
_in is a DOM relation marker which specifies that the element should be searched within another
element.
For example, in the above case, the second delete link is near User Two.

_link(0, _near(_cell("User Two"))) points to the 0th link near cell with text User Two.
Note that the index is 0 here since it is the nearest link.
_link("delete", _near(_cell("User Two"))) points to the nearest link with text delete near cell
with text User Two.
Note that we do not need to specify "delete[1]" since it
is the delete link nearest to User Two.
_link(/del/, _near(_cell("User Two"))) points to the nearest link with text which matches
regular expression /del/ near cell with text User Two.
_link("delete[2]", _near(_cell("User Two"))) points to the 3rd nearest link with text delete near cell
with text User Two.
_link("/del/[2]", _near(_cell("User Two"))) points to the 3rd nearest link with text matching /del/
near cell with text User Two.
Note how the regular expression is appended with the
index in square brackets and quoted to make it a string

A similar DOM relation is _in


Sahi Pro Tyto Software Pvt. Ltd. 60

_link(0, _in(_cell("del2"))) points to the 0th link in cell with id del2
_link("delete", _in(_cell("del2"))) points to the link with text delete within cell with id del2


Positional Relations

Positional Relations help narrow down elements which are positioned relative to another element. For
example, this can be used to find a textbox to the right of a label, or an Edit link to the left of a User
name.
Postitional Relation APIs: _under, _above, _aboveOrUnder, _leftOf, _rightOf, _leftOrRightOf
Illustration: _under is a Positional Relation which helps narrow down elements under another element.
Specifically it looks for elements which have the same left offset (within a threshold) as the anchoring
element. One important frequent requirement in web applications is the assertion of elements in a
column of a grid.
For example
Name Delete Status
User One delete Active
User Two delete Inactive

<table>
<tr>
<td>Name</td>
<td>Delete</td>
<td>Status</td>
</tr>
<tr>
<td>User One</td>
<td id="del1"><a href="/deleteUser?id=1">delete</a></td>
<td>Active</td>
</tr>
<tr>
<td>User Two</td>
<td id="del2"><a href="/deleteUser?id=2">delete</a></td>
<td>Inactive</td>
</tr>
</table>

In the above table:


Sahi Pro Tyto Software Pvt. Ltd. 61


_cell(0, _near(_cell("User One")), _under(_cell("Status"))) Finds first cell near User One and under
Status
_cell("Inactive", _under(_cell("Status"))) Finds first Inactive cell under Status

Other APIs are explained below in the APIs section.

Accessors of HTML Elements:
API _link(identifier[, domRelation])
HTML <a href="http://u/r/l" id="id">visible text</a>
Identifier index, visible text, id
Example _link("Sahi Website");

API _image(identifier[, domRelation])
HTML <img src="/path/to/images/add.gif" id="id" alt="alt" title="title">
Identifier index, title or alt, id, file name from src
Notes _image(add.gif) for an image with src /path/to/images/add.gif
Example _image("title");

API _label(identifier[, domRelation])
HTML <label id="id">text</label>
Identifier index, id, text
Example _label("text");

API _listItem(identifier[, domRelation])
HTML <li id="id">text</li>
Identifier index, id, text
Example _listItem("text");

API _div(identifier[, domRelation])
HTML <div id="id">text</div>
Identifier index, id, text
Example _div("text");



Sahi Pro Tyto Software Pvt. Ltd. 62

API _span(identifier[, domRelation])
HTML <span id="id">text</span>
Identifier Index,id,text
Example _span("text");



API _spandiv(identifier[, domRelation])
HTML <span id="id">text</span> or <div id="id">text</div>
Identifier Index, id, text
Example _spandiv("text");

API _heading1(identifier[, domRelation])
HTML <h1 id="id">text</h1>
Identifier text, id
Example _heading1("text");

API _heading2(identifier[, domRelation])
HTML <h2 id="id">text</h2>
Identifier text, id
Example _heading2("text");

API _heading3(identifier[, domRelation])
HTML <h3 id=id>text</h3>
Identifier text, id
Example _heading3("text");

API _heading4(identifier[, domRelation])
HTML <h4 id=id>text</h4>
Identifier text, id
Example _heading4("text");



Sahi Pro Tyto Software Pvt. Ltd. 63

API _heading5(identifier[, domRelation])
HTML <h5 id=id>text</h5>
Identifier text, id
Example _heading5("text");

API _heading6(identifier[, domRelation])
HTML <h6 id=id>text</h6>
Identifier text, id
Example _heading6("text");

API _title()
HTML <title>text</title>
Notes Returns title of the page
Example _title("text");

API _area(identifier[, domRelation])
HTML <area shape="rect" class="className" id="id" href="http://u/r/l" />
Identifier id, title|alt, href, shape, className, index
Example _area("id");

API _blockquote(identifier[, domRelation])
HTML <blockquote class="className" id="id">sahiText</blockquote>
Identifier sahiText, id, className, index
Example _blockquote("sahiText");

API _bold(identifier[, domRelation])
HTML <b class="className" id="id">sahiText</b>
Identifier sahiText, id, className, index
Example _bold("sahiText");



Sahi Pro Tyto Software Pvt. Ltd. 64

API _code(identifier[, domRelation])
HTML <code class="className" id="id">sahiText </code>
Identifier sahiText, id, className, index
Example _code("sahiText");

API _emphasis(identifier[, domRelation])
HTML <em class=className id=id>sahiText</em>
Identifier sahiText, id, className, index
Example _emphasis("sahiText");

API _italic(identifier[, domRelation])
HTML <i class="className" id="id">sahiText</i>
Identifier sahiText, id, className, index
Example _italic("sahiText");
API _list(identifier[, domRelation])
HTML <ul class="className" id="id">sahiText</ul>
<ol class="className" id="id">sahiText</ol>
Identifier id, className, index
Example _list("sahiText");

API _map(identifier[, domRelation])
HTML <map class="className" id="id"></map>
Identifier name, id, title, className, index
Example _map("id");

API _canvas(identifier[, domRelation])
HTML <canvas class=classname id=id></canvas>
Identifier sahiText, id, className, index
Example _canvas("id");



Sahi Pro Tyto Software Pvt. Ltd. 65

API _preformatted(identifier[, domRelation])
HTML <pre class="className" id="id">sahiText</pre>
Identifier sahiText, id, className, index
Example _preformatted("sahiText");

API _strong(identifier[, domRelation])
HTML <strong class="className" id="id">sahiText</strong>
Identifier sahiText, id, className, index
Example _strong("sahiText");

API _abbr(identifier[, domRelation])
HTML <abbr class="className" id="id">sahiText</abbr>
Identifier sahiText, id, className, index
Example _abbr("sahiText");
Since 2011-07-19

Accessors of Table related elements
API _cell(identifier[, domRelation])
HTML <td id="id">text</td>
Identifier index, id, sahiText, className
Example _cell("text");

API _cell(tableElement, rowText, colText)
HTML <td id="id">text</td>
<table id="tableId">
<tr><td> header1 </td><td> header2 </td><td> header3 </td></tr>
<tr><td> value11 </td><td> value12 </td><td> value13 </td></tr>
<tr><td> value21 </td><td> value22 </td><td> value23 </td></tr>
</table>
Example _cell(_table("tableId"), "header2", "value11");
This will point to cell with valuevalue11



Sahi Pro Tyto Software Pvt. Ltd. 66

API _row(identifier[, domRelation])
HTML <tr><td>te</td><td>xt</td></tr>
Identifier id, className, sahiText, index
Notes _row(text) can be used to identify rows with text. Useful to look for cells in a
row.
_cell(text1,_in(_row(someClassName)))
Example _row("text");

API _table(identifier[, domRelation])
HTML <table id="id">text</table>
Identifier index, id, className
Example _table("text");

API _tableHeader(identifier[, domRelation])
HTML <th id="id">text</th>
Identifier sahiText, id, className
Example _tableHeader("text");

Accessors of Form elements
API _button(identifier[, domRelation])
HTML <input type="button" name="name" id="id" value="value">
<button type="button" name="name" id="id">value</button>
Identifier value, name, id, index, className (sahiText: valid for <button/>)
Example _button("value");

API _checkbox(identifier[, domRelation])
HTML <input type=checkbox name=name id=id value=value>
Identifier name, id, value, className, index
Example _checkbox("name");

API _password(identifier[, domRelation])
HTML <input type="password" name="name" id="id" value="value">
Identifier name, id, index, className
Example _password("name");



Sahi Pro Tyto Software Pvt. Ltd. 67

API _radio(identifier[, domRelation])
HTML <input type="radio" name="name" id="id" value="value">
Identifier id, name, value, className, index
Example _radio("id");

API _submit(identifier[, domRelation])
HTML <input type="submit" name="name" id="id" value="value">
<button type="submit" name="name" id="id">value</button>
Identifier value, name, id, className, index (sahiText: valid for <button/>)
Example _submit("value");

API _textbox(identifier[, domRelation])
HTML <input type="textbox" name="name" id="id" value="value">
Identifier name, id, index, className
Example _textbox("name");

API _reset(identifier[, domRelation])
HTML <input type="reset" name="name" id="id" value="value">
<button type="reset" name="name" id="id"> value</button>
Identifier value, name, id, index, className (sahiText: valid for <button/>)
Example _reset("value");

API _file(identifier[, domRelation])
HTML <input type="file" name="name" id="id" value="value">
Identifier name, id, index, className
Example _file("name");

API _imageSubmitButton(identifier[, domRelation])
HTML <input type="image" name="name" id="id" value="value" alt="alt" title="title"
src="/images/file.gif">
Identifier title|alt, name, id, fileName, index, className
Example _imageSubmitButton("title");
_imageSubmitButton("file.gif");



Sahi Pro Tyto Software Pvt. Ltd. 68

API _select(identifier[, domRelation])
HTML <select name="name" id="id"></select>
Identifier name, id, index, className
Example _select("id");

API _option(identifier[, domRelation])
HTML <option id="id" value="value">text</option>
Identifier sahiText, value, id, index
Notes _option(selectElement, identifier) has been phased out since 2010-06-10.
Please use _option(identifier, _in(selectElement)) instead.
Example _option("text");
_option("text",_in(_select("selectedId")));

API _textarea(identifier[, domRelation])
HTML <textarea name="name" id="id">text</textarea>
Identifier name, id, index, className
Example _textarea("name");

API _hidden(identifier[, domRelation])
HTML <input type="hidden" name="name" id="id" value="value">
Identifier name, id, className, index
Example _hidden("id");

Accessors of HTML5 Form elements
API _timebox(identifier)
HTML <input type="time" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _timebox("name");

API _datebox(identifier)
HTML <input type="date" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _datebox("name");



Sahi Pro Tyto Software Pvt. Ltd. 69

API _datetimebox(identifier)
HTML <input type="datetime" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _datetimebox("name");

API _datetimelocalbox(identifier)
HTML <input type="datetime-local" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _datetimelocalbox("name");

API _weekbox(identifier)
HTML <input type="week" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _weekbox("name");

API _monthbox(identifier)
HTML <input type="month" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _monthbox("name");

API _numberbox(identifier)
HTML <input type="number" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _numberbox("name");

API _rangebox(identifier)
HTML <input type="range" name="name" id="id" value="value" min="min" max
="max"/>
Identifier name, id, index, className
Example _rangebox("name");



Sahi Pro Tyto Software Pvt. Ltd. 70

API _telephonebox(identifier)
HTML <input type="tel" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _telephonebox("name");

API _emailbox(identifier)
HTML <input type="email" name="name" id="id" value="value"/>
Identifier name, id, index, className
Example _emailbox("id");

API _urlbox(identifier)
HTML <input type="url" name="name" id="id" value="value"/>
Identifier index, name, id
Example _urlbox("name");

API _searchbox(identifier)
HTML <input type="search" name="name" id="id" value="value"/>
Identifier Index, name, id
Example _searchbox("name");

Accessors of parent DOM Nodes
All parent node accessors can take two parameters:
element: The element whose parent node needs to be found
occurrence: The n
th
parent. 1 is the immediate parent.
For example,
In <div id="div2"><span><div id="div1"><a href="">aLink</a></div></span></div>
_parentNode(_link("aLink"), "DIV", 1); points to div1
_parentNode(_link("aLink"), "DIV", 2); points to div2
API _parentNode(element, tagname[, occurrence])
HTML <div id="id"><a href="http://u/r/l">aElement</a></div>
Example _parentNode("DIV", _link("aElement")); may return _div("id");



Sahi Pro Tyto Software Pvt. Ltd. 71

API _parentCell(element[, occurrence])
HTML <td id="id"><a href=" http://u/r/l ">aElement</a></td>
Example _parentCell(_link("aElement"));

API _parentRow(element[, occurrence])
HTML <tr><td>aCell</td></tr>
Example _parentRow(_cell("aCell"));

API _parentTable(element[, occurrence])
HTML <table class="api">
<tr><td>aCell</td></tr></table>
Example _parentTable(_cell("aCell"));

Accessors of IFrames and Rich Text Editors based on IFrames in editable mode
API _rte(identifier)
HTML <iframe src="" name="name" id="id" ></iframe>
Identifier name, id, index
Example _rte("id");

API _iframe(identifier)
HTML <iframe src="" name="name" id="id" ></iframe>
Identifier name, id, index
Example _iframe("id");




Sahi Pro Tyto Software Pvt. Ltd. 72

Generic accessors
API _byId(id)
HTML <anytag id="id" ></anytag>
Identifier id
Notes This can be used for any tag with an id. This API does not accept regular
expressions or indexes.
Example _byId("id");

API _byText(identifier, tagName)
HTML <anytag>text</anytag>
Identifier text
Notes This can be used for any tag with text.
Example _byText("text");

API _byClassName(identifier, tagName[, domRelation])
HTML <anytag class="className">text</anytag>
Identifier className
Example _byClassName("text");

API _byXPath(xpath[, domRelation])
Identifier xpath expression as string .
This is a convenience method for people moving from Selenium or other tools to
Sahi.
Notes XPaths are natively enabled on Firefox. For browsers like Internet Explorer which
do not have support for XPath use Javascript-XPath. Copy the contents of
javascript-xpath-latest.js and save the contents to sahi/htdocs/spr/ext/javascript-
xpath/javascript-xpath.js and there is a README.txt which has these instructions

This file is under its own MIT license and is not part of Sahis code base
Example _byXPath("//table[3]//tr[1]/td[2]");
_byXPath("//tr[1]/td[2]", _in(_table(2)));

API _accessor(string)
Notes This API just evaluates the string and returns a dom object. This API is not too
useful.
Example _accessor("document.formName.elementName");



Sahi Pro Tyto Software Pvt. Ltd. 73

Browser popups: Alerts, Confirms and Prompts
Browser popus are of three types:
Alert Box
Confirm Box
Prompt Box
Sahi does not display browser popups during playback. However, the content from these popups is
made available so that assertions can be made on it.
API _lastAlert()
Notes Returns the message displayed in the last javascript alert popup.
Example Consider this HTML snippet:
<input type="button" onclick="alert('abc')"value="Click Me">
The following test will click the button and assert that abc was alerted.
_click(_button("Click Me"));
_assertEqual("abc", _lastAlert());

API _lastConfirm()
Notes Returns the message displayed in the last javascript confirm popup
_lastConfirm returns the text of the last confirm which occured.
Example Consider this HTML snippet:
<input type="button" onclick="confirm('Did you get it?')"value="Click Me">
The following test will click the button and assert that Did you get it? was
confirmed.
_click(_button("Click Me"));
_assertEqual("Did you get it?", _lastConfirm());

API _lastPrompt()
Notes Returns the message displayed in the last javascript prompt popup.
_lastPrompt returns the text of the last prompt which occured.
Example Consider this HTML snippet:
<input type="button" onclick="prompt('Enter Name')"value="Click Me">
If a user enters Ram in the prompt box, the following test will click the button
and assert that Ram was entered.
_click(_button("Click Me"));
_expectPrompt("Enter name", "Ram");
_assertEqual("Ram", _lastPrompt());
Since the prompt is not displayed during playback, the _expectPrompt API should
be used to enter value in the prompt. Refer to _expectPrompt for more details.



Sahi Pro Tyto Software Pvt. Ltd. 74

API _printCalled()
Notes Returns true if window.print() had been invoked
Example _printCalled();



Utility functions to access properties of elements
API _style(element, cssProperty)
cssProperty Any property declared via CSS i.e., height, background-color etc
Notes Returns the value of the style property for that element.
HTML <td style="background-color:red">cell text</td>
Example _style(_cell("cell text"), "background-color"); returns rgb(255, 0, 0)

API _cookie(cookieName)
Notes Returns the value of the cookie with cookieName.
Example _cookie("SESSID");
This may return 44159b7fdf524e97015f1982e65990d2

API _position(element)
Notes Returns the array with the elements x, y coordinate in pixels.
Example _position(_div("id"));
If the div is present present at (100, 180), _position(el) will return [100, 180].

API _getText(element)
HTML <div id=divId>This is some <b>bold</b> <a href=#>link</a></div>
Notes Returns the innerText or textContent of an element.
Example _getText(_div("divId")); will return This is some bold link



Sahi Pro Tyto Software Pvt. Ltd. 75

API _getCellText(cellElement)
HTML <td id=dataId>cell text</td>
Notes Returns the innerText or textContent of an element.
Same as _getText
Example _getCellText(_cell("dataId"));

API _getSelectedText(selectElement)
Notes Returns the text of the selected option in a <select>tag
Example Consider this HTML snippet:
<select id="age"><option>21</option><option>32</option></select>
If 32 is the selected option, then
_getSelectedText(_select("age")); may return 32

API _rteHTML(element)
Notes Returns the html inside a rich text editor.
Example _rteHTML(_rte("rteId")); will return the rich text editors contents.

API _rteText(element)
Notes Returns the text inside a rich text editor.
Example _rteText(_rte("rteId")); will return the rich text editors text content (without the
html formatting).

API _isVisible(element)
Notes Returns true if the HTML element is visible on the user interface. This API uses the
CSS visibility (style.visibility.hidden) or display property (style.display.none) to
determine the visibility of an element. Can be used to assert if a mouse over menu
has appeared or not.
Example _isVisible(_div("divId"));

API _exists(element)
Notes Returns true if the HTML element exists. Same as checking element != null.
Example _exists(_link("Login"));



Sahi Pro Tyto Software Pvt. Ltd. 76

API _containsText(element, text)
HTML <div id="divId">some text displayed here</div>
Notes Returns true if the element contains the given text
Example _containsText(_div("divId"), "some"); returns true

API _containsHTML(element, html)
HTML <div id="divId">some <b>text</b></div>
Notes Returns true if the element contains the given html
Example _containsHTML(_div("divId"), "<b>text</b>") ; returns true

API _contains(parentElement, childElement)
HTML <div id="id"><a href="http://u/r/l">aElement</a></div>
Notes Returns true if childElement is a child of parentElement
Example _contains(_div("id"), _link("aElement"));

API _extract(string, pattern, groupsOnly)
Notes Returns an array of matching elements. Pattern needs to be a valid regular
expression. Eg. In the string

"The traffic light changed from red to green"

With groupsOnly = false

Pattern Returns
"/from .* to .*/" ["from red to green"]
"/from (.*) to .*/" ["from red to green", "red"]
"/from (.*) to (.*)/" ["from red to green", "red", "green"]

With groupsOnly = true

Pattern Returns
"/from .* to .*/" []
"/from (.*) to .*/" ["red"]
"/from (.*) to (.*)/" ["red", "green"]
Example
var $expected = ["red", "green"];
var $str = "The traffic light changed from red to green";
var $pattern = "/from (.*) to (.*)/";
var $extracted = _extract($str, $pattern, true);
_assertEqual($expected, $extracted);

Demo Script
extract.sah



Sahi Pro Tyto Software Pvt. Ltd. 77



Marker functions to show DOM relation
API _in(element)
Notes Refer DOM Relations

API _near(element)
Notes Refer DOM Relations

Marker functions to show Positional relation
API _xy(element, x, y)
Notes Specifies the coordinates on element where the event is fired.
Example _click(_xy(_button("id"), 10, 20));
clicks inside the button, 10px from the left and 20 pixels from the top.
Negative values can be given to specify offset from right and bottom.
_click(_xy(_button("id"), -5, -10));
clicks inside the button, 5px from the right and 10px from the bottom.

API _under(element[, offset, limitUnder])
Notes Refer Positional Relations
offset: number in pixels. For elements not exactly aligned vertically, the offset
specifies the maximum allowed difference in their x coordinates.
limitUnder: number in pixels. Maximum distance under the given element till
which Sahi will look.
Example
_textbox(0, _under(_cell("Total")));

API _above(element[, offset, limitAbove])
Notes Similar to _under but searches above an element. When used with an index, the
indexing starts from the top of the page. This can be limited with limitAbove.
offset: number in pixels. For elements not exactly aligned vertically, the offset
specifies the maximum allowed difference in their x coordinates.
limitAbove: number in pixels. Maximum distance above the given element till
which Sahi will look. Give a value like 20 to look immediately above an element.
Example
_textbox(0, _above(_cell("Total"), 0, 20));



Sahi Pro Tyto Software Pvt. Ltd. 78

API _aboveOrUnder(element[, offset])
Notes Finds an element vertically aligned with given element
offset: number in pixels. For elements not exactly aligned vertically, the offset
specifies the maximum allowed difference in their x coordinates.
Example
_textbox(0, _aboveOrUnder(_cell("Total")));

API _leftOf(element[, offset])
HTML
<input type="checkbox"><label>Name:</label>
Notes Allows finding an element to the left of another element. When used with an
index, the indexing starts from the left of the page.
offset: number in pixels. For elements not exactly aligned horizontally, the offset
specifies the maximum allowed difference in their y coordinates.
Example
_checkbox(0, _leftOf(_label("Name:")));

API _rightOf(element[, offset])
HTML
<label>Name:</label><input type="text">
Notes Allows finding an element solely to the left of another element
offset: number in pixels. For elements not exactly aligned horizontally, the offset
specifies the maximum allowed difference in their y coordinates.
Example
_textbox(0, _rightOf(_label("Name:")));

API _leftOrRightOf(element[, offset])
HTML
<label>Name:</label><input type="text">
Notes Allows finding an element horizontally aligned with another element
offset: number in pixels. For elements not exactly aligned horizontally, the offset
specifies the maximum allowed difference in their y coordinates.
Example
_textbox(0, _leftOrRightOf(_label("Name:")));




Sahi Pro Tyto Software Pvt. Ltd. 79

Browser Action APIs
These APIs perform actions on the browser.
The remarkable thing about these Browser Action APIs, is that the parameter expressions
passed to these APIs execute on the browser and not on the proxy.
For example,
_click(document.form1.checkbox1) will work since document.form1.checkbox1 is evaluated on the
browser.
Note: Sahi Pro is shipped with working examples that can be found in
<SAHI_HOME>/userdata/scripts/demo/

Mouse Actions
API _click(element, combo)
Notes Clicks the element.
Syntax _click( element[, combo] )
element: HTML element to click
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _click(_button("Click Me"));
_click(_button("Click Me"), "CTRL"); // clicks with CTRL key pressed
_click(_button("Click Me"), "CTRL|SHIFT"); // clicks with CTRL and SHIFT keys
pressed
Demo Script clicksTest.sah

API _rightClick(element, combo)
Notes Right clicks on an element.
Syntax _rightClick( element[, combo] )
element: HTML element to right click
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _rightClick(_button("Right Click Me"));
_rightClick(_button("Right Click Me"), "CTRL"); // clicks with CTRL key pressed
_rightClick(_button("Right Click Me"), "CTRL|SHIFT"); // clicks with CTRL and SHIFT
keys pressed
Demo Script clicksTest.sah



Sahi Pro Tyto Software Pvt. Ltd. 80

API _doubleClick(element, combo)
Notes Double clicks on an element.
Syntax _doubleClick( element[, combo] )
element: HTML element to double click on
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _doubleClick(_button("Double Click Me"));
_doubleClick(_button("Double Click Me")); // doubleClicks with CTRL key pressed
_doubleClick(_button("Double Click Me") "CTRL|SHIFT"); // doubleClicks with
CTRL and SHIFT keys pressed
Demo Script clicksTest.sah

API _check(element)
Notes Checks the given checkbox or radio element. If already checked, this API does not
do anything.
Syntax _check( element )
element: element to be checked. Element should be a checkbox or radio element.
Example _check("checkboxName");
_check("radioName");
Demo Script checkbox.sah

API _uncheck(element)
Notes Unchecks the given checkbox. If already unchecked, this API does not do anything.
Syntax _uncheck( element)
element: element to be unchecked. Element should be a checkbox.
Example _uncheck("checkboxName");
Demo Script checkbox.sah














Sahi Pro Tyto Software Pvt. Ltd. 81

API _mouseOver(element, combo)
Notes Simulates a mouse over on the element.
Syntax _mouseOver( element[, combo] )
element: HTML Element to hover over
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _mouseOver(_button("Click Me"));
_mouseOver(_button("Click Me"), "CTRL"); // mouseOver with CTRL key pressed
_mouseOver(_button("Click Me"), "CTRL|SHIFT"); // mouseOver with CTRL and
SHIFT keys pressed
Demo Script mouseEvents.sah

API _mouseDown(element, isRight, combo)
Notes Simulates a mouse down on the element.
Syntax _mouseDown( element[, isRight, combo] )
element: HTML element to perform a mouse down on
isRight (Optional): Set to true for a left-hand mouse
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _mouseDown(_button("Mouse Down"));
_mouseDown(_button("Mouse Down"),true);
_mouseDown(_button("Mouse Down"), false, "CTRL"); //mouseDown with CTRL
key pressed
_mouseDown(_button("Mouse Down"), false, "CTRL|SHIFT"); //mouseDown with
CTRL and SHIFT keys pressed
Demo Script mouseEvents.sah



Sahi Pro Tyto Software Pvt. Ltd. 82

API _mouseUp(element, isRight, combo)
Notes Simulates a mouse up on the element.
Syntax _mouseUp( element[, isRight, combo] )
element: HTML element to perform a mouse up on
isRight (Optional): Should be true for a left-hand mouse
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _mouseUp(_button("Mouse Down"));
_mouseUp(_button("Mouse Down"),true);
_mouseUp(_button("Mouse Down"), false, "CTRL"); //mouseUp with CTRL key
pressed
_mouseUp(_button("Mouse Down"), false, "CTRL|SHIFT"); //mouseUp with CTRL
and SHIFT keys pressed
Demo Script mouseEvents.sah

API _simulateMouseEvent(element, type, isRight, isDouble, combo)
Notes Simulates any mouse event on an element.
Syntax _simulateMouseEvent( element, type[, isRight, isDouble, combo] )
element: HTML element to trigger the mouse event on
type: Mouse event type. Eg. mousedown, mouseup, mouseover, mousemove
isRight (Optional): Should be true for a left-hand mouse
isDouble (optional): Should be true for a double click.
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _simulateMouseEvent(_button("Mouse Event"), "mousedown");

API _simulateMouseEventXY(element, type, x, y, isRight, isDouble, combo)
Notes Simulates a mouse event on an element and triggers the event at (x, y)
coordinates. The default coordinates are (0, 0)
Syntax _simulateMouseEvent( element, type[, x, y, isRight, isDouble, combo] )
element: HTML element to trigger the mouse event on
type: Mouse event type. Eg. mousedown, mouseup, mouseover, mousemove
x: x coordinate to trigger the event from
y: y coordinate to trigger the event from
isRight (Optional): Should be true for a left-hand mouse
isDouble (optional): Should be true for a double click.
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _simulateMouseEventXY(_button("Mouse Event"), "mousedown", 10, 5);




Sahi Pro Tyto Software Pvt. Ltd. 83


API _dragDrop(draggable, droppable, offsetX, offsetY)
Notes Drags elementToDrag and drops on elementToDropOn
Syntax _dragDrop( draggable, droppable[, offsetX, offset] )
draggable: HTML element to be dragged
droppable: HTML Element where the draggable will be dropped
offsetX (Optional): X coordinate from where the drop event is triggered
offsetY (Optional): Y coordinate from where the drop event is triggered
Example _dragDrop(_image("item"), _byId("ShoppingCart"));
This will drag the item and drop it in the shopping cart

Drag and Drop is not a native event till HTML4. So events are synthesized in Sahi
for some generic cases which may not work for every framework.
(HTML5 has native drag drop capabilities).
To fix this, you could write your own function using the various _mouseXXX APIs.
For example, to dragDrop on a GWT grid, you may use:

function gwtDragDrop($dragEl, $dropEl){
_mouseDown($dragEl);
_mouseOver($dragEl);
_mouseOver($dropEl);
_mouseUp($dropEl);
}
gwtDragDrop(_span("drag me"), _span("drop on me"));

For multi-window drag drops, the code may look something like this:
function dragDropMultiwin($win1, $dragEl, $win2, $dropEl){
_selectWindow($win1);
_mouseDown($dragEl);
_mouseOver($dragEl);
_selectWindow($win2);
_mouseOver($dropEl);
_mouseUp($dropEl);
}
dragDropMultiwin("window1", _span("drag me"), "window2", _span("drop on
me"));

Normally the drag event is triggered at coordinate (0, 0) of an element. If your
element needs to be clicked somewhere in between, say 10px from left and 5px
from top, use this example:
_dragDrop(_xy(_image("item"),10,5), _byId("ShoppingCart"));
Demo Script dragDrop.sah



Sahi Pro Tyto Software Pvt. Ltd. 84

API _dragDropXY(draggable, x, y, isRelative)
Notes Drags elementToDrag and drops it on the given x, y coordinates.
Syntax _dragDropXY(draggable, x, y[, isRelative])
draggable: HTML Element to be dragged
x: x coordinate of drop point on the page
y: y coordinate of drop point on the page
isRelative (Optional): Specifies whether the coordinates are relative to current
position of draggable element.
Example If _image("item") is located at coordinates (50, 150)
_dragDropXY(_image("item"), 100, 300);
will drag the item and drop it at the coordinate (100, 300)
The end result is that the elements coordinates will be at (100, 300)

_dragDropXY(_image("item"), 100, 300, true);
will drag the item and drop it at the coordinate (50+100, 150+300)
The end result is that the elements coordinates will be at (150, 450)
Demo Script dragDropXY.sah

Focus Actions
API _focus(element)
Notes Brings focus to element.
Syntax _focus(element)
element: Element to bring to focus
Example _focus(_textbox("username"));
Demo Script focusTest.sah

API _removeFocus(element)
Notes Removes focus from element.
Syntax _removeFocus(element)
element: Element to remove focus from
Example _removeFocus(_textbox("username"));
Demo Script focusTest.sah



Sahi Pro Tyto Software Pvt. Ltd. 85

API _blur(element)
Notes Removes focus from element.
Syntax _blur(element)
element: Element to remove focus from
Example _blur(_textbox("username"));
Demo Script focusTest.sah

Key Actions
API _keyPress(element, charInfo, combo)
Notes Simulates a keypress event for key with given charInfo on the element.
Syntax _keyPress(element, charInfo[, combo])
element: HTML element to press the key on
charInfo: character or character code or array of [keyCode, charCode]
combo (Optional): ): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _keyPress(_textbox("t2"), 'a'); //Set a in textbox
_keyPress(_textbox("t2"), 97); //Set a in textbox
_keyPress(_textbox("t2"), 'a', "ALT"); //Enter a with ALT key pressed
Demo Script keypress.sah

API _keyDown(element, charInfo, combo)
Notes Simulates a keydown event for key with given charInfo on the element.
Syntax _keyDown(element, charInfo[, combo])
element: HTML element to invoke the keydown on
charInfo: character or character code or array of [keyCode, charCode]
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _keyDown(_textbox("t2"), 'a');
_keyDown(_textbox("t2"), 97);
_keyDown(_textbox("t2"), 'A', "SHIFT");
_keyDown(_textbox("t2"), [13,0]); //Press enter key
Demo Script google_search_dd.sah



Sahi Pro Tyto Software Pvt. Ltd. 86

API _keyUp(element, charInfo, combo)
Notes Simulates a keyup event for key with given charInfo on the element.
Syntax _keyUp(element, charInfo[, combo])
element: HTML element to invoke the keyup on
charInfo: character or character code or array of [keyCode, charCode]
combo (Optional): Any combo key; can be CTRL, SHIFT, ALT or META;
Can also be two or more keys together like CTRL|SHIFT
Example _keyUp(_textbox("t2"), 'a');
_keyUp(_textbox("t2"), 97);
_keyUp(_textbox("t2"), 'A', "SHIFT");
_keyUp(_textbox("t2"), [13,0]); //Press enter key
Demo Script google_search_dd.sah

Data Input Actions
API _setValue(element, text)
Notes Focuses on the element, types in the text and then removes focus from element.
element can be a textarea or a textbox
Syntax _setValue(element, value)
element: HTML Form Element whose value needs to be set
value: String value
Example _setValue(_textbox("username"), "karthik");
_setValue(_textarea("address"), "Somewhere there");
_setValue(_password("password"), "secret");
Demo Script textarea.sah



Sahi Pro Tyto Software Pvt. Ltd. 87

API _setSelected(element, option_identifier[, isMultiple])
Notes Selects the option with option_identifier in select element.
Syntax _setSelected ( element, option_identifier, isMultiple)
element: HTML select element
option_identifier: Options text, id or index; can also pass an array of options for
multi-select
isMultiple (Optional): true for multiselect
Example _setSelected(_select("Age"), "28");
_setSelected(_select("color"), 1); // Selects the second option in a select box
_setSelected(_select("color"), red); // Selects red in a multiselect box
_setSelected(_select("color"), blue, true); // Selects blue also in the multiselect
box
_setSelected(_select("color"), [red, blue]); // Unselects previous and selects red
and blue in a multiselect box
_setSelected(_select("color"), [1,2,3]); // Unselects previous and selects the
second, third and fourth options in a multiselect box
_setSelected(_select("color"), [green, yellow], true); // Keeps previous options
selected and selects green and yellow also
Demo Script select.sah









Sahi Pro Tyto Software Pvt. Ltd. 88

API _setFile(element, filePath)
Notes Prepares the form to set file at filePath.
Syntax _setFile(element, filePath [, actionURL])
element: HTML Form File Element whose value needs to be set
filePath: Path of the file to be uploaded.
actionURL (Optional): The form action URL to which the file is submitted. This is an
optional parameter. Use it in cases where the forms action URL is changed on
setting the file. By default, it uses the forms current action URL.
Example _setFile(_file("id"), "C:\\abc\\efg.jpg");
_setFile(_file("id"), "C:\\abc\\efg.jpg", "formSubmit.jsp");

Note that _setFile works in a roundabout way. It is not handled at the browser
level. It is handled at the proxy. So you will not see the file input box being
populated with your desired filename. But when the form is submitted, the proxy
will add the correct file to the request before it sends it to your web server. But if
there are javascript checks before form submit to see if the filename is non-empty,
then the script will not work as desired.
If there are javascript validations on the file field, you can try this hack. Before
submitting the file, change the fields type to text, and then set its value like this


// set the file
_setFile(_file("file"), "scripts/demo/uploadme.txt");
// Change the "type" attribute of file field
if (_isIE()){
_call(_file("file").outerHTML = _file("file").outerHTML.replace(/type=file/,
"type=text"));
}else{
_call(_file("file").type = "text");
} // Set the value into the textbox
_setValue(_textbox("file"), "scripts/demo/uploadme.txt");

Demo Script fileUpload.sah

API _rteWrite(iframe, text)
Notes Writes text into a rich text editor based on content-editable iframe
Syntax _rteWrite(iframe, text)
iframe: editable iframe
text: text to insert into the iframe
Example _rteWrite(_rte("editorId"), "Welcome Karthik");
Iframes in design mode (contentEditable true) are considered Rich Text Editors
(RTE) by Sahi.



Sahi Pro Tyto Software Pvt. Ltd. 89

API _type(element, text)
Notes Types the text into the element. Different from _setValue.
_type does not bring or remove focus from element. Rarely used.
Syntax _type(element, text)
element: HTML element to type into
text: text to be inserted
Example _type(_textbox("a"), "text input");

Assertions
The following APIs will log messages into the report on assertion failure ONLY
DO NOT USE THIS IN AN IF CONDITION as it does not return any value, and throws an exception if the
expected and actual values are not equal.
API _assertEqual(expected, actual, message)
Notes Asserts that expected and actual are equal, else logs the message.
Syntax _assertEqual( expected, actual, message )
expected: expected value - can be a number, string, array or regular expression
actual: actual value
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertEqual("abc", "abc", "Some Log Message");
This does nothing
_assertEqual("abc", "def", "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertNotEqual(expected, actual, message)
Notes Asserts that expected and actual are NOT equal, else logs the message.
Syntax _assertNotEqual( expected, actual, message )
expected: expected value (can be a number, string, array or regular expression)
actual: actual value
message: Message to be written to logs if the expected and actual values are not
equal

Example _assertNotEqual("abc", "def", "Some Log Message");
This does nothing
_assertNotEqual("abc", "abc", "Some Log Message");
This throws exception and writes Some Log Message to logs.




Sahi Pro Tyto Software Pvt. Ltd. 90


API _assertNotNull(object, message)
Notes Asserts that the object is NOT null, else logs the message.
Syntax _assertNotNull( object, message )
object: Any object
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertNotNull("abc");
This does nothing
_assertNotNull(null, "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertNull(object, message)
Notes Asserts that the object is null, else logs the message.
Syntax _assertNull( object, message )
object: Any object
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertNull(null);
This does nothing
_assertNotNull("abc", "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertTrue(condition, message)
Notes Asserts that the condition is true, else logs the message.
Syntax _assertTrue( condition, message )
condition: Boolean expression
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertTrue(1==1);
This does nothing
_assertTrue(1==2, "Some Log Message");
This throws exception and writes Some Log Message to logs.







Sahi Pro Tyto Software Pvt. Ltd. 91


API _assert(condition, message)
Notes Asserts that the condition is true, else logs the message. Same as _assertTrue
Syntax _assert( condition, message )
condition: Boolean expression
message: Message to be written to logs if the expected and actual values are not
equal
Example _assert (1==1);
This does nothing
_assert (1==2, "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertNotTrue(condition, message)
Notes Asserts that the condition is NOT true, else logs the message.
Syntax _assertNotTrue( condition, message )
condition: Boolean expression
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertNotTrue(1==2);
This does nothing
_assertNotTrue(1==1, "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertFalse(condition, message)
Notes Asserts that the condition is false, else logs the message.
Syntax _assertFalse( condition, message )
condition: Boolean expression
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertFalse(1==2);
This does nothing
_assertFalse(1==1, "Some Log Message");
This throws exception and writes Some Log Message to logs.







Sahi Pro Tyto Software Pvt. Ltd. 92


API _assertExists(object, message)
Notes Asserts that the object is not null, else logs the message.
Syntax _assertExists( object, message )
object: Any object
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertExists(_link("Back to form"));
This does nothing
_assertExists(null, "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertNotExists(object, message)
Notes Asserts that the object does not exist (is null), else logs the message.
Syntax _assertNotExists( object, message )
object: Any object
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertNotExists(null);
This does nothing
_assertNotExists(_link("Back to form"), "Some Log Message");
This throws exception and writes Some Log Message to logs.

API _assertContainsText(expectedText, object, message)
Notes Asserts that the object contains the expectedText, else logs the message.
Syntax _assertContainsText( expectedText, object, message )
expectedText: Text expected to be present. This can be replaced with a regular
expression.
object: Any object
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertContainsText("Invalid Login", _div("login_section"), "Text was not
present");
_assertContainsText(/[Ii]nvalid/, _div("login_section"), "Text was not present");
_assertContainsText("Invalid Login", _div("login_section"));
_assertContainsText(/[Ii]nvalid/, _div("login_section"));



Sahi Pro Tyto Software Pvt. Ltd. 93

API _assertNotContainsText(expectedText, object, message)
Notes Asserts that the object does not contain the expectedText, else logs the message.
Syntax _assertNotContainsText( expectedText, object, message )
expectedText: Text expected not to be present. This can be replaced with a regular
expression.
object: Any object
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertNotContainsText("Invalid Login", _div("login_section"), "Text was
present");
_assertNotContainsText(/[Ii]nvalid/, _div("login_section"), "Text was present");
_assertNotContainsText("Invalid Login", _div("login_section"));
_assertNotContainsText(/[Ii]nvalid/, _div("login_section"));

API _assertEqualArrays(expected, actual, message)
Notes Asserts that expected and actual arrays are equal, else logs the message.
Syntax _assertEqualArrays( expected, actual, message )
expected: expected array
actual: actual array
message: Message to be written to logs if the expected and actual values are not
equal
Example _assertEqualArrays([1,2,3],[1,2,3]);
This does nothing
_assertEqualArrays([1,2,3],[1,2,4] , "Some Log Message");
This throws exception and writes Some Log Message to logs.
NOTE: This is internally called by _assertEqual if expected and actual are arrays

Utility actions
API _navigateTo(url, forceReload)
Notes Navigates to the given url.
Syntax _navigateTo( url, forceReload )
url: URL to navigate to.
forceReload: when set to true, refreshes the page.
Example _navigateTo("http://sahi.co.in");
_navigateTo("http://sahi.co.in", true);



Sahi Pro Tyto Software Pvt. Ltd. 94

API _closeWindow()
Notes Closes the current window.
This will work ONLY for popups.
Syntax _closeWindow()
Example _popup("popWin")._closeWindow();

API _log(message, logLevel)
Notes Logs message into the playback logs.
Syntax _log( message, logLevel )
message: Message to log
type: where type can be success, failure, error, info, custom(1 - 5)
Example _log("Message", "failure"); Output: Message
_log("Message ", "success"); Output: Message
_log("Message ", "error"); Output: Message
_log("Message ", "info"); Output: Message
_log("Message ", "custom"); Output: Message
_log("Message ", "custom1"); Output: Message
_log("Message ", "custom2"); Output: Message
_log("Message ", "custom3"); Output: Message
_log("Message ", "custom4"); Output: Message
_log("Message ", "custom5"); Output: Message

API _wait(maxTime, condition)
Notes Waits for timeInMilliseconds ms or till the condition is satisfied on the browser,
whichever is sooner.
Syntax _wait( maxTime, condition )
maxTime: Time in milliseconds after which execution will resume
condition: (Optional) Condition which when satisfied will resume execution
Example _wait(1000);
Will stop execution for a second
_wait(1000, _byId("ajaxy").innerHTML!="");
Will wait till div by id ajaxy is populated or one second, whichever occurs sooner
Demo Script wait_for.sah








Sahi Pro Tyto Software Pvt. Ltd. 95

API _call(javascriptSnippet)
Notes Executes the javascriptSnippet on the browser, instead of in the Rhino engine.
Syntax _call( javascriptSnippet )
javascriptSnippet : Javascript to be invoked in on the browser.
Example
<browser>
function toggleTreeWidget(){
// some javascript to toggle a tree widget
}
</browser>
_call(toggleTreeWidget());
_call(location.href = "xxx");


Note: To fetch a value from a function on the browser and store it a variable in
script, use _set

<browser>
function getRowCount(){
return _table("t1").rows.length;
}
</browser>
var $count;
_set ($count, getRowCount());
// Use $count
_alert($count);

Important: Sahi will evaluate the content in <browser> on the browser instead of
the rhino engine.
_call should be used sparingly and only if none of the inbuilt Sahi Browser Action
APIs work.



Sahi Pro Tyto Software Pvt. Ltd. 96

API _set( $variableName, value )
Notes _set is used to fetch the value of a page dependent variable (something that is part
of the browser page) and store it in a Sahi variable. You would need this to access
Javascript attributes not already exposed by Sahis APIs.
Syntax _set( $variableName, value )
$variableName: variable to assign the value to
value: value to assign. Note that the value should not be a javascript object which
has attributes which reference itself.
Example If we wish to get the href of a link,
var $href;
_set($href, _link("my link").href); // store
// you may do other actions or navigate to other pages
_assertEqual("http://sahi.co.in", $href); //use
Note that there is no Sahi API to retrieve the href property directly. For retrieving
text using _getText, _set is not required.
var $text = _getText(_link("linkId"));
Another example with a browser function:
<browser>
function getRowLength(){
return _table("t1").rows.length;
}
</browser>
var $count=0;
_set ($count, getRowLength());
_alert($count);










Sahi Pro Tyto Software Pvt. Ltd. 97

API _eval(string)
Notes Evals the string on the browser, instead of in the Rhino engine.
Syntax _eval(string)
string: String to evaluate
Example _eval("document.form1.complicatedWidget.click()");

Note: _call is different from _eval. _eval takes a string.
_call(toggleTreeWidget());
This is the same as
_eval("toggleTreeWidget()");

API _callServer(cmd, qs)
Notes Calls server side code which cannnot be executed by javascript on the
browser.
Syntax _callServer(cmd, qs)
cmd: String command of the form className_methodName
qs: QueryString to be made available in the invoked method
Example Below is an implementation of writing debug messages to the console.
Create this class:

package net.sf.sahi.ext;
import net.sf.sahi.request.HttpRequest;
public class Debug {
public void toOut(HttpRequest request) {
String msg = request.getParameter("msg");
System.out.println(msg);
}
}

Add it to Sahis classpath:
Look at Adding jars to Sahis classpath

Call this from your script:
_callServer("net.sf.sahi.ext.Debug_toOut", "msg=SomeMessage");
This will write SomeMessage on the console where sahi was started.

Since Sahi V2, these actions can directly be performed by calling java classes from
javascript through Rhino.





Sahi Pro Tyto Software Pvt. Ltd. 98

API _savedRandom( id, min, max )
Notes Stores a random number against an id.
First invocation: Returns a random number between min and max
Subsequent calls with the same id: Returns the number that it had returned the
first time for the given id.
Syntax _savedRandom( id, min, max )
id: Any string
min: Lower limit for the number generated
max: Upper limit for the number generated
Example _savedRandom("login", 100, 200);
returns a random number between 100, 200; say 145.
_savedRandom("login", 100, 200);
will return 145, since it was saved against the id "login".
The min and max are redundant here.
_savedRandom("login"); will also return 145.

API _resetSavedRandom(key)
Notes Resets the random number associated with key, to another random number.
From Sahi V2, random numbers can be generated using _random and stored as
simple variables.
Syntax _resetSavedRandom( key )
key: Id of the _savedRandom that needs to be reset
Example _savedRandom("a", 10, 30); // returns a random number, say 23
_savedRandom("a", 10, 30); // returns 23
_savedRandom("a"); // returns 23
_resetSavedRandom("a");
_savedRandom("a"); // returns null
_savedRandom("a", 10, 30); // returns another random number

API _random(max)
Notes Returns a random number between 0 and max
Syntax _random( max )
max: Upper limit for the number generated
Example _random(10);
may generate any number between 0 and 10.








Sahi Pro Tyto Software Pvt. Ltd. 99

API _setGlobal(key, value)
Notes Stores the value in key for retrieval.
The value persists across tests in a suite, if suite.global_variables is true in
sahi.properties.
Syntax _setGlobal( key, value )
key: identifier
value: value associated with the key
Example _setGlobal("userid1", _textbox("user").value);

API _getGlobal (key)
Notes Gets a previously stored variable whose scope will span a session.
Globals are used for persisting variables across multiple web pages.
Syntax _getGlobal ( key )
key: String identifying a global variable
Example _setGlobal("name", "Ram");
_getGlobal("name"); // will return "Ram"

API _collect(apiType, id, inEl)
Notes Collects all elements of a particular type and stores them in an array.
Syntax _collect(apiType, id[, inEl])
apiType: The type of API to collect
id: A common identifier
inEl (Optional): Parent element containing the elements to collect.
Example var $els = _collect ("_link", "/group 1/", _in(_div("div1")));
$els is an array of all links containing the text group 1.
_assertEqual("group 1 link3", _getText($els[0]));
Demo Script collect.sah

API _count(apiType, id, inEl)
Notes Counts all elements of a particular type and stores them in a variable.
Syntax _count(apiType, id, inEl)
apiType: The type of API to count
id: A common identifier
inEl (Optional): Parent element containing the number of elements to count.
Example var $c = _count ("_link", "/group 1/");
$c may have a count of all links containing the text, group 1.
_assertEqual(5, $c);
Demo Script collect.sah



Sahi Pro Tyto Software Pvt. Ltd. 100

Actions to mock out particular URLs
Mocks are used to mock out responses to urls which match a particular pattern.
For example:
A web page has embedded advertisements in an iframe and we do not wish to test these
advertisements everytime we test our web page.
We can add a mock by specifying this to our script.
_addMock("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds");
Whenever Sahi encounters a URL request which matches www[.]adserver[.]com
It will delegate the response handling to sahi.ext.MyCustomMocks filterAds method.
One can call any classs any method, as long as the method has one of these two signatures.
public net.sf.sahi.response.HttpResponse
methodName (net.sf.sahi.request.HttpRequest request);

public void methodName(net.sf.sahi.request.HttpRequest request);

If _addMock(pattern) is called without a second parameter,
net.sf.sahi.command.MockResponder.simple(HttpRequest) is used to process the request.
This response uses template at sahi/htdocs/spr/simpleMock.htm.
One can modify this to show a generic mock response. By default this response just shows the mocked
url.
For images, one can use _mockImage, which is the same as _addMock except that it by default calls
net.sf.sahi.command.MockResponder.mockImage(HttpRequest) which returns a simple image at
sahi/htdocs/spr/mock.gif
API _addMock(pattern[, clazz_method])
Notes Forces the proxy to process certain patterns of urls differently.
If clazz_method is not specified, sends back a simple HTML blank page.
Syntax _addMock(pattern[, clazz_method])
pattern: pattern to match
clazz_method: method to send the response to
Example _addMock("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds");
Demo Script mock.sah



Sahi Pro Tyto Software Pvt. Ltd. 101

API _mockImage(pattern[, clazz_method])
Notes Similar to _addMock, but by default sends back an image.
Syntax _mockImage(pattern[, clazz_method])
pattern: pattern to match
clazz_method: method to send the response to
Example _mockImage("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds");

API _removeMock(pattern)
Notes Removes the mock behavior added via _addMock or _mockImage for that pattern.
Syntax _removeMock(pattern)
pattern: pattern to match
Example _removeMock(".*sahi[.]co[.]in.*");
Demo Script mock.sah


















Sahi Pro Tyto Software Pvt. Ltd. 102

Actions to set expectations for javascript confirms and prompts
API _expectConfirm(message, boolean)
Notes Sets an expectation such that when a javascript confirm with given message
appears, based on the boolean value, OK or Cancel will be processed. Should be
used before the statement that triggers the confirm dialog.
Syntax _expectConfirm( message, boolean )
message: The visible text on the confirm dialog
boolean: Expected boolean return value.
Example _expectConfirm("Some question?", true);
Here, ok will be processed

Javascript calls to confirm( msg ) are mocked out by Sahi so that it does not stop
playback. Sahi by default acts as if OK was clicked when a confirm dialog comes
up.
It is possible to make the confirm return as if it was cancelled by setting
_expectConfirm("Some question?", false);
before the statement which triggers the confirm dialog.
If there was no expectation set, Sahi will return true.
It is also possible to get the text of the last occurred confirm dialog using
_lastConfirm();
Demo Script confirm.sah

API _expectPrompt(message, text)
Notes Sets an expectation such that when a javascript prompt with given message
appears, the given text is populated. Should be included before the statement that
triggers a prompt.
Syntax _expectPrompt( message, text )
message: The visible text on the prompt dialog
text: Input value
Example _expectPrompt("Some prompt?", "abc");
This will make the prompt return abc and can be accessed with _lastPrompt();
Javascript calls to prompt( msg ) are mocked out by Sahi so that it does not stop
the playback. Sahi by default returns if a prompt dialog comes up.
If there was no expectation set, Sahi will return .
Demo Script prompt.sah



Sahi Pro Tyto Software Pvt. Ltd. 103

API _clearPrintCalled()
Notes resets the value of _printCalled
Syntax _clearPrintCalled()
Example _clearPrintCalled();
Demo Script print.sah

API _clearLastAlert()
Notes Clears the value returned by _lastAlert()
Syntax _clearLastAlert()
Example _clearLastAlert();
Demo Script alert.sah

API _clearLastPrompt()
Notes Clears the value returned by _lastPrompt()
Syntax _clearLastPrompt()
Example _clearLastPrompt();
Demo Script prompt.sah

API _clearLastConfirm()
Notes Clears the value returned by _lastConfirm()
Syntax _clearLastConfirm()
Example _clearLastConfirm();
Demo Script confirm.sah
Actions used for debugging
API _highlight(element)
Notes Highlights an element with a red border. Use only for debugging.
Syntax _highlight(element)
element: HTML element to highlight
Example _highlight(_div("Average")); This may look like this Average



Sahi Pro Tyto Software Pvt. Ltd. 104

API _alert(message)
Notes Brings up a javascript alert with given message. Use only while debugging.
Syntax _alert(message)
message: message to show in alert
Example _alert("Some message?");

API _confirm(message)
Notes Brings up a javascript confirm with given message. Use only while debugging
Syntax _confirm(message)
message: message to show in confirm box
Example _confirm("Do you wish to continue?");

API _debug(message)
Notes Prints the message on to the console for debugging purposes.
Syntax _debug(message)
message: Message to print on the console
Example _debug("Some message");

API _debugToErr(message)
Notes Prints the message on to the error stream for debugging purposes.
Syntax _debugToErr(message)
message: Message to print
Example _debugToErr("Some message");

API _debugToFile(message, filePath)
Notes Prints the message into a file for debugging purposes.
Syntax _debugToFile(message, filePath)
message: Message to print
filePath: Path of the file
Example _debugToFile("Some message", "C:/errors.txt");






Sahi Pro Tyto Software Pvt. Ltd. 105

Toggle KeepAlive Actions
API _enableKeepAlive()
Notes Turns on Keep-Alive. It is used in conjunction with _disableKeepAlive() on pages
which hang because of flash objects or applets.
Syntax _enableKeepAlive()
Example _disableKeepAlive();
_call(loadPageWithFlashWhichHangsOtherwise());
_enableKeepAlive();

API _disableKeepAlive()
Notes Turns off Keep-Alive. It is used in conjunction with _enableKeepAlive() on pages
which hang because of flash objects or applets.
Syntax _disableKeepAlive()
Example _disableKeepAlive();
_call(loadPageWithFlashWhichHangsOtherwise());
_enableKeepAlive();

Cookie related actions
API _createCookie(name, value, days)
Notes Creates a cookie with name and value which will expire in given days.
Syntax _createCookie(name, value, days)
name: Name of the cookie
value: Value to be stored in the cookie
days: Number of days till expiry
Example _createCookie("__login__sessid", "4rf6thbsk8t234hdi5673", 4);
This will create a cookie called __login__sessid valid for 4 days

API _deleteCookie(name)
Notes Deletes cookie with given name.
Syntax _deleteCookie(name)
name: Name of the cookie
Example _deleteCookie("__login__sessid");
may delete a cookie with the name __login__sessid







Sahi Pro Tyto Software Pvt. Ltd. 106

Additionally, Sahi lets a user view all the cookies that are set during a session in a web application. This is
available in http://domain.com/_s_/dyn/Cookies_showAll


Download related actions
Sahi handles file downloads by silently downloading files into sahi/temp/download folder.
The last downloaded file can be manipulated by the following APIs.
Note that a _wait() statement may be required before _saveDownloadedAs in case the file is big and
takes a lot of time to download.
Sahis proxy detects file downloads, and automatically saves them to sahi/userdata/temp/download
directory. Sahi also adds the sessionId to the file name, so that multiple simultaneous tests do not
overwrite each others files.
So if you were clicking on a download link which downloads a setup.exe file, this is how Sahi will
handle it.
1) Click on download link
2) Sahi detects that it is a downloadable file, based on its MimeType and Content-Disposition headers.
It then downloads and saves the file into sahi/userdata/temp/download/ after renaming it to
something like: sahi_0384a26207e6104f5f08868032bd170de76d__setup.exe
3) Once the file is downloaded Sahi exposes the original name of the file (setup.exe) through the API:
_lastDownloadedFileName()
4) Another API, _saveDownloadedAs, allows the file to be renamed and copied over to a convenient
directory for you to work on.
5) API: _clearLastDownloadedFileName clears out the _lastDownloadedFileName() so that further files
can be downloaded and worked upon.


Sahi Pro Tyto Software Pvt. Ltd. 107

More information:
Sahi detects that a file is to be downloaded, based on
1. content type (configurable via sahi/userdata/config/download_contenttypes.txt)
2. The Content-Disposition: attachment header
3. Whether the URL is configured in sahi/userdata/config/download_urls.txt
If you see a file download dialog during playback, do the following:
1. Check if the download URL follows a specific pattern. If yes, add the pattern of the URL to
download_urls.txt
For example, if your download url is
http://mysite.example.com/export_doc.jsp?id=12318812 ,
add
.export_doc[.]jsp.
to download_urls.txt
2. If there are multiple files that are to be downloaded, and they all are of a particular content-
type, add the content type to download_contenttypes.txt
3. If your file download response always has content-disposition as attachment, you can tell sahi
to download them by default by setting
download.download_if_contentdisposition_is_attachment=true
in sahi/userdata/config/userdata.properties
File Download Response:
Normally, when a file is downloaded, the browser should not navigate away from the current page. This
is accomplished by Sahi by sending back a 204 response header. But in some cases, when a PDF is to be
opened in a new window, the PDF will be downloaded by Sahi but a blank window will be left open
which cannot be controlled by Sahi. In such cases, force Sahi to send back an HTML response, by adding
_sendHTMLResponseAfterFileDownload(true)
before the click step which triggers the download. Using _popup(/.*/)._closeWindow() will close the
window.

API _saveDownloadedAs(filePath)
Notes Saves the file which was downloaded into sahi/temp/folder into the given filePath
Syntax _saveDownloadedAs(filePath)
filePath: Path where the file should be saved
Example _saveDownloadedAs("c:/path/myfile.txt");
Demo Script save_as.sah



Sahi Pro Tyto Software Pvt. Ltd. 108

API _clearLastDownloadedFileName()
Notes Clears the _lastDownloadedFileName (so that new files downloaded with the same
fileName can be asserted)
Syntax _clearLastDownloadedFileName()
Example _clearLastDownloadedFileName();
Demo Script save_as.sah

API _sendHTMLResponseAfterFileDownload (boolean)
Notes Normally Sahi sends back a 204 response so that the browser stays on the same
page. Using _sendHTMLResponseAfterFileDownload (true) forces Sahi to return
back an HTML response. This is needed when your application triggers the
download from a new window (eg. with a PDF or a word doc). Add this before the
step which triggers the download.
Syntax _sendHTMLResponseAfterFileDownload (boolean)
boolean: true or false
Example _sendHTMLResponseAfterFileDownload(true);
_sendHTMLResponseAfterFileDownload(false);

Demo Script download_in_popup.sah




Sahi Pro Tyto Software Pvt. Ltd. 109

Miscellaneous APIs
Functions available on browser and on proxy
API _scriptName()
Notes Returns the name of the current script
Example _scriptName(); may return keypress.sah

API _scriptPath()
Notes Returns the path of the current script
Example _scriptPath(); may return C:/keypress.sah

API _popup(identifier)
Notes Returns a handle to the window. The identifier can be a regular expression.
_popup() is used as a prefix to statements which need to be executed on another
window.
Syntax _popup( identifier )
identifier: windowName, windowTitle
Example _popup("popWin")._click(_link("Click me"));
_popup(/popWin.*/)._click(_link("Click me"));
_popup("Window Title")._click(_link("Click me"));
Demo Script popup_title.sah

API _selectWindow(popupIdentifier)
Notes Sets the given window as context for the following Sahi statements.
The identifier can be a regular expression.
This API helps make scripting easier when most actions are performed on a popup
window.
Syntax _selectWindow( popupIdentifier )
popupIdentifier: windowName, windowTitle;
if left blank, it chooses the base window
Example _selectWindow("popWin"); //select popWin
//further statements will be performed on popWin
_click(_link("Click me"));// will click on popWin
_selectWindow(); // select base window
// further statements will be performed on base window
_click(_button("Finished")); // clicks on base window;
Demo Script popup_title.sah



Sahi Pro Tyto Software Pvt. Ltd. 110

API _sessionInfo()
Notes Returns information of the current session. The object has attribures: isRecording
isPlaying isPaused sessionId
Example _sessionInfo();

API _suiteInfo()
Notes Returns information of the current session.
Example _suiteInfo();

API _userDataDir()
Notes Returns absolute path to userdata directory.
Example _userDataDir();
may return C:/sahi_pro/userdata/

API _userDataPath(relativePath)
Notes Returns absolute path to userdata directory, given a relative path.
Example _userDataPath("scripts");
may return C:/sahi_pro/userdata/scripts/

API _lastDownloadedFileName()
Notes Returns the name of the last downloaded file name.
Example _assertNull(_lastDownloadedFileName()); // nothing so far
_click(_link("download")); // click on download link
_assertEqual("setup.exe", _lastDownloadedFileName()); // check if downloaded
_saveDownloadedAs("c:/path/myfile.txt"); // save to another path
_clearLastDownloadedFileName(); // clear the variable
_assertNull(_lastDownloadedFileName()); // check to see if cleared.



Sahi Pro Tyto Software Pvt. Ltd. 111

API _setStrictVisibilityCheck(boolean)
Notes This API is useful in cases where widgets are dynamically created at multiple
locations but only one of them is visible at any given time.

During recording Sahi can be forced into either mode by choosing Strict Visibility
On or Strict Visibility Off from the Other Actions: dropdown. Make sure you
Append to Script to add it to the recorded script
Example _setStrictVisibilityCheck(true);
makes Sahi ignore elements which are not visible.
_setStrictVisibilityCheck(false);
makes sahi revert to original behavior of considering all elements in the DOM.
Demo Script strict_visible.sah




















Sahi Pro Tyto Software Pvt. Ltd. 112

Functions available on proxy only
API _logException(exception)
Notes Exceptions are handled via regular javascript try catch blocks since Sahi V2.
Syntax try{
// sahi statements
}catch(exception) {
// Corrective action
_logException( exception ); // Can print exact source of error in log
// Can throw the same or another exception
}
exception: exception to log
Example Corrective Action:
try{
_click(_link("does not exist"));
}catch(e) {
_log("Exception occured"); // simple logging. no failure
_click(_link("linkByHtml")); // Corrective action
}
Corrective Action and Log the Exception Message:
try{
_click(_link("does not exist"));
}catch(e) {
_click(_link("linkByHtml")); // Corrective action
_logException(e); // Logs the exception, but does not fail
}

API _stopOnError()
Notes Makes the script stop if an error occurs. This is the default behavior.
Example _stopOnError();

API _continueOnError()
Notes Makes script continue inspite of errors. Can be turned off with _stopOnError()
Example _continueOnError();



Sahi Pro Tyto Software Pvt. Ltd. 113

API _logExceptionAsFailure(exception)
Notes Exceptions are handled via regular javascript try catch blocks since Sahi V2
Syntax try{
// sahi statements
}catch(exception){
// Corrective action
_logExceptionAsFailure( exception ); // Can print exact source of error in log
// Can throw the same or another exception
}
Example Corrective Action:
try{
_click(_link("does not exist"));
}catch(e){
_log("Exception occured"); // simple logging. no failure
_click(_link("linkByHtml")); // Corrective action
}
Corrective Action, Log and then Fail:
try{
_click(_link("does not exist"));
}catch(e){
_click(_link("linkByHtml")); // Corrective action
_logExceptionAsFailure(e); // Logs the exception, and fails,
// and in the logs, points to the original line as source of failure.
}
Demo Script log_exception_as_failure.sah


















Sahi Pro Tyto Software Pvt. Ltd. 114

Recovery functions

Sometimes it is necessary to do some corrective action in case a test fails half way through.
This is different from try-catch because we do not want the script to continue; we just want the state of
our system to be restored to a sensible point.
The relevant APIs are:
_setRecovery(fn);
_removeRecovery(fn);
Any function can be assigned to a script as a recovery function. Once set, if there is an error during
execution, the recovery function will be called before the script stops.

API _setRecovery(fn)
Notes Sets fn as recovery function. The function will be called before the script exits, if
and only if there is a failure in the script. It can be turned off with
_removeRecovery().
Syntax _setRecovery( fn )
fn: recovery function
Example _navigateTo("http://sahi.co.in/demo/");
function myRecoveryFn(){
_alert("In myRecoveryFn."); // This statement will be alerted in case of script
error.
}
_setRecovery(myRecoveryFn); // Set the myRecoveryFn as recovery function.
_click(_link("Link Test")); // Works normally
_click(_link("Bad Link"));
// This statement fails and causes myRecoveryFn to be called.
_alert("done");
// This statement will not be called, because script failed in the last statement.



Sahi Pro Tyto Software Pvt. Ltd. 115

API _removeRecovery(fn)
Notes Removes any recovery function which was set via _setRecovery(fn).
Syntax _removeRecovery(fn)
fn: recovery function
Example _navigateTo("http://sahi.co.in/demo/");
function myRecoveryFn(){
_alert("In myRecoveryFn.");
// The above statement will be alerted in case of script error.
}
_setRecovery(myRecoveryFn); // Set the myRecoveryFn as recovery function.
_click(_link("Link Test")); // Works normally
_click(_link("Bad Link"));
// This statement fails and causes myRecoveryFn to be called.
_alert("done");
// This statement will not be called, because script failed in the last statement.
_removeRecovery(myRecoveryFn);




Sahi Pro Tyto Software Pvt. Ltd. 116

Working with Excel Sheets

Sahi Pro V4+ lets you access Excel Sheets using _getExcel() API.
API _getExcel(excelFilePath, sheetName)
Notes Allows manipulation of Excel files. This is a replacement of the older way of
accessing excel sheets using _getDB.
Syntax _getExcel(excelFilePath, sheetName)
excelFilePath: absolute or relative path to Excel file
sheetName: Name of the sheet
Demo Script getExcel.sah
Example Given below


//Set Data
var $excel = _getExcel("C:\\poiTest.xls","Sheet1");
var $excelData=[
["ajay","babu","cheeran"],
["david","elango","frank"],
["gokul","hari","irfan"],
["jo","kumar","latha"],
["mani","naraen","ojha"],
["peter","queen","richard"],
["shalini","thomas","umesh"]
];

$excel.setData($excelData);
var $data=$excel.getData();
_assertEqual("elango",$data[1][1],"Values are Equal");

//Get Data
var $getdata=$excel.getData();
_assertEqual("irfan",$getdata[2][2],"Values are Equal");

//Insert New Row
var $insertRowData=["varun","wargees","xezwanth"];
var $insertRowIndex=3;
$excel.insertRow($insertRowData,$insertRowIndex);
var $dataAfterInsertRow=$excel.getData();
_assertEqual("wargees",$dataAfterInsertRow[3][1],"values are Equal");

//Insert New Rows
var
$insertRowsData=[["yamini","eeswar","sasi"],["durai","ojasna","sukrith"]];
var $insertRowsIndex=4;
$excel.insertRows($insertRowsData,$insertRowsIndex);
var $dataAfterInsertRows=$excel.getData();
_assertEqual("sasi",$dataAfterInsertRows[4][2],"Values Match");





Sahi Pro Tyto Software Pvt. Ltd. 117


Contd

//Delete Row
var $deleteRowIndex=4;
$excel.deleteRow($deleteRowIndex);
var $dataAfterRowDelete=$excel.getData();
_assertNotEqual("sasi",$dataAfterRowDelete[4][2],"Values didnot Match");

//Delete Rows
var $deleteRowsIndexes=[1,4];
$excel.deleteRows($deleteRowsIndexes);
var $dataAfterDeleteRows=$excel.getData();
_assertNotEqual("Paudyal",$dataAfterDeleteRows[1][1],"Values didnot Match");
_assertEqual("wargees",$dataAfterDeleteRows[2][1],"Values Matched");

//Get Cell Value
var $excelGet=$excel.get(2,2);
_assertEqual("xezwanth",$excelGet,"Values Matched");

//Set Cell Value
var $excelData=$excel.set(2,2,"444-444-4444");
var $dataAfterSet=$excel.getData();
_assertEqual("444-444-4444",$dataAfterSet[2][2],"Values Matched");





Sahi Pro Tyto Software Pvt. Ltd. 118

Working with databases
Sahi has an API that will allow the user to connect to various databases using the _getDB API
This API returns a sahiDB object which has two methods
select(sql) used for select statements
update(sql); used for update/delete/insert statements

To start working with _getDB API, it is necessary to have the appropriate driver to connect to a
database. This driver has to be present in Sahis external classpath.
More info: Adding jars to Sahis classpath

select( sql ): The result set that is returned by the select statement is a list of rows. Rows are accessible
by index.
For example:
ID NAME AGE
1
2
3
Kamalesh
Arun
Raja
28
30
35
For this table, we have:
var db = _getDB("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@dbserver:1521:sid",
"username", "password");
var $rs = db.select("select * from User");


$rs[0][NAME] may return Kamalesh
$rs[0] may return the first row
$rs[1][ID] may return 2
NOTE: The columns in a row are accessible by their column names (not column index).



Sahi Pro Tyto Software Pvt. Ltd. 119

API _getDB(driver, jdbcurl, username, password)
Notes Returns a DB object which can be used to query the database.
_getDB is used to connect to a database.
Syntax _getDB(driver, jdbcurl, username, password)
driver: JDBC driver class
jdbcurl: JDBC URL
username: username to connect to the database
password: password to connect to the database
Example For table User

ID NAME AGE
1
2
3
Kamalesh
Arun
Raja
28
30
35


var db = _getDB("oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@dbserver:1521:sid", "username", "password");
var $rs = db.select("select * from User");
_assertEqual("2", $rs[1]["ID"]);
_assertEqual("Kamlesh", $rs[0]["NAME"]);
_assertEqual("28", $rs[0]["AGE"]);


Looping through results:
Here is an example which loops through the results, and calls a custom function.
var db = _getDB("oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@dbserver:1521:sid",
"username", "password");
var $rs = db.select("select * from User");
for (var $i=0; $i < $rs.length; $i++){
var $row = $rs[$i];
var $name = $row["NAME"];
var $age = $row["AGE"];
// pass name and age to your custom function like processNameAge
processNameAge($name, $age);
}
Demo Script db.sah




Sahi Pro Tyto Software Pvt. Ltd. 120

OLDER DOCUMENTATION - NOT RECOMMENDED USE _getExcel INSTEAD
You can also connect to an excel sheet with _getDB.
On Windows, you could use the jdbc:odbc driver to access Excel. This does not need any extra jars.
NOTE: On 64 bit windows, you need to download and install the 64 bit ODBC drivers (Download and
install AccessDatabaseEngine_x64.exe)
For example:
Given an excel sheet C:\\myfolder\\sample.xls, with the following data:
Name Age Sex
Raju
Ramu
Sheela
20
30
25
Male
Male
Female

// Get the DB instance
var db = _getDB("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:Driver={Microsoft Excel Driver (*.xls,
*.xlsx, *.xlsm, *.xlsb)};DBQ=D:\\myfolder\\sample.xls;readOnly=false", "", "");
// Run a select
$rs = db.select("select * from [Sheet1$]");
// Assert the first row has Raju in the Name column
_assertEqual("Raju", $rs[0]["Name"]);
// Assert the first row has 20 in the Age column.
// All values will be strings, so we need to parseInt the age.
_assertEqual(20, parseInt($rs[0]["Age"]));
// Run an update.
db.update("update [Sheet1$] set Age=21 where Name='Raju'");
// Do a select again to verify
$rs = db.select("select * from [Sheet1$]");
_assertEqual(21, parseInt($rs[0]["Age"]));

Note the readOnly=false in the connection string on the first line. This is required if you wish to update
the Excel sheet.
If you do not add readOnly=false, you will get an error like this:
java.sql.SQLException: [Microsoft][ODBC Excel Driver] Operation must use an updateable query.








Sahi Pro Tyto Software Pvt. Ltd. 121

Working with files
API _readFile(filePath)
Notes Returns the contents of the file as a single String.
This is the simplest way of reading a files contents.
Syntax _readFile( filePath )
filePath: Path of file to read. Paths are relative to the scripts location. Specify
absolute path if the file should be read from any other path.
Example var $contents = _readFile("C:/contents.txt");
Here, $contents is a string that contains text from contents.txt
Demo Script readfile.sah

API _writeFile(text, filePath[, overwrite])
Notes Writes the text into file at filePath.
Syntax _writeFile( text, filePath[, overwrite] )
text: text to write
filePath: Path of file to write to. Paths are relative to the scripts location. Specify
absolute path if the file should be created in any other path.
overwrite: true if contents of file need to be overwritten. Default: false
Example _writeFile("some text", "C:/info.txt");
The contents of info.txt will be some text.
Note: If the file is not available, it is automatically created at the path

API _writeToFile(text, filePath[, overwrite])
Notes Writes the text into file at filePath.
Syntax _writeToFile( text, filePath[, overwrite] )
text: text to write
filePath: Path of file to write to. Paths are relative to the scripts location. Specify
absolute path if the file should be created in any other path.
overwrite: true if contents of file need to be overwritten. Default: false
Example _writeToFile("some text", "C:/info.txt");
The contents of info.txt will be some text.
Note: If the file is not available, it is automatically created at the path



Sahi Pro Tyto Software Pvt. Ltd. 122

API _readCSVFile(filePath, wordSeparator)
Notes Reads a csv file and returns a 2 dimensional array of the contents. If the separator
between words is not a comma, it can be specified as the second parameter.
Syntax _readCSVFile(filePath, wordSeparator)
filePath: Path of the CSV file to read. Paths are relative to the scripts location.
Specify absolute path if the file should be read from any other path.
wordSeparator: Separator between words. Default: , (comma)
Example var $data = _readCSVFile("simple.csv", "|");
var $row = null ;
for (var $i=0; $i<$data.length; $i++){
for (var $j=0; $j<$data[$i].length; $j++){
_click(_link($data[$i][$j]));
}
}
This example reads contents from a | separated CSV file which contains a list of
link identifiers. A click action is then performed on each of these links.
Demo Script csv.sah

API _writeCSVFile(array2d, filePath, overwrite, wordSeparator)
Notes Writes a 2 dimensional array into a file in CSV format, using the given
wordSeparator (default is comma)
Syntac _writeCSVFile( array2d, filePath[, overwrite, wordSeparator] )
array2d: 2 dimensional array
filePath: Path of the file to write to. Paths are relative to the scripts location.
Specify absolute path if the file should be created in any other path.
overwrite: if true, overwrites the file. Default: false
wordSeparator: Separator between words
Example var $ar = new Array();
$ar[$ar.length] = [ "hi", "there", "one", "a\"b"];
_writeCSVFile($ar, "sahicsv.txt", true);
Demo Script csv.sah

API _deleteFile(filePath)
Notes Deletes the file at filePath.
Syntax _deleteFile(filePath)
filePath: Path of the file to delete. Paths are relative to the scripts location.
Specify absolute path if the file should be deleted from any other path.
Example _deleteFile("sahicsv.txt");



Sahi Pro Tyto Software Pvt. Ltd. 123

API _renameFile(oldFilePath, newFilePath)
Notes Renames (or moves) a given file from oldFilePath to newFilePath. If newFilePath
already exists, it will be overwritten
Syntax _renameFile( oldFilePath, newFilePath )
oldFilePath: Path of file to rename / move
newFilePath: New path
Example _renameFile("sahicsv.txt", "C:/newSahiCSV.txt");

Data driven testing
Sahi has some nice inbuilt features for data-driven testing. The core concept is that data is present as a
grid of rows and columns, and tests need to run with each row of the grid as input.
Suppose we have a 2-dimensional array of data, on which we perform an add operation:
function doAdd($first, $second, $total){
_setValue(_textbox("first"), $first);
_setValue(_textbox("second"), $second);
_click(_button("Add"));
_assertEqual($total, _textbox("total").value);
}
var $data = [[2, 3, 5],
[1, 2, 4],
[4, 3, 7]]

A simple way to do this is to iterate over the array and invoke the doAdd function with values from each
row.
for (var $i=0; $i<$data.length; $i++){
var $row = $data[$i];
doAdd($row[0], $row[1], $row[2]);
}

But, this loop will fail in the second row, since 1+2=3 and not 4, as given in the second row. In case of
failure we need to continue to the next row and not stop there. To do this, we use a try catch block.
for (var $i=0; $i<$data.length; $i++){
var $row = $data[$i];
try{
doAdd($row[0], $row[1], $row[2]);
} catch (e) {
// The try catch block helps in continuing with the next
// step of data inspite of failures.
// _logException so that the logs will indicate the failing line.
_logException(e);
}}



Sahi Pro Tyto Software Pvt. Ltd. 124

All this looping and try catch have been neatly wrapped into a utility function _dataDrive.
API _dataDrive(fn, data2DArray)
Notes Loops over data2DArray, and invokes function fn with each row of data. The
invocation is within a try catch block with exception logging.
Syntax _dataDrive(fn, data2DArray)
fn: function to call
data2DArray: 2 dimensional array to iterate over
Example function doAdd($first, $second, $total){
_setValue(_textbox("first"), $first);
_setValue(_textbox("second"), $second);
_click(_button("Add"));
_assertEqual($total, _textbox("total").value);
}
var $data = [
[2, 3, 5],
[1, 2, 4],
[4, 3, 7]
]
_dataDrive(doAdd, $data);
Note that the function itself is passed to _dataDrive. (No open close brackets after
doAdd).
Instead of $data being hard coded in the test, you can read it from a CSV
file/database or excel sheet. For example, the above code could become

var $data = _readCSVFile("path/to/data_file.csv");
_dataDrive(doAdd, $data);


Sahi can read and write to CSV (Comma Separated Value) files, databases and Excel sheets.
Other APIs that can be used for data driven testing are:
_readCSVFile()
_writeCSVFile()
_getDB()
_getExcel()






Sahi Pro Tyto Software Pvt. Ltd. 125

APIs for browser detection
API _isIE(), _isIE9()
Notes Returns true if browser is Internet Explorer

API _isFF(), _isFF2(), _isFF3(), _isFF4(), isFF5()
Notes Returns true if browser is Mozilla Firefox

API _isChrome()
Notes Returns true if browser is Google Chrome

API _isSafari()
Notes Returns true if browser is Safari

API _isOpera()
Notes Returns true if browser is Opera

APIs for screen capture
There are two APIs that capture the state of the screen for a step during script execution.
_takeSnapShot()
_takeSnapShots( toggle )
API _takeSnapShot()
Notes Used to take a snapshot of a single step
Example _click(_link("Click me"));
_takeSnapShot();
This will capture the state of the screen when the link Click me is clicked.
Demo Script createSnapShot.sah



Sahi Pro Tyto Software Pvt. Ltd. 126

API _takeSnapShots(toggle)
Notes Used when snapshots are necessary for multiple steps
Syntax _takeSnapShots(toggle)
toggle: set to true to start capturing screenshots. Should be set to false to stop
capturing screenshots.
Example _takeSnapShots (true); //Start screen capture
_setValue(_password("password"), "secret"); //Screenshot taken
_click(_submit("Login")); //Screenshot taken
_takeSnapShots (false); //Stop screen capture
Demo Script createSnapShot.sah





















Sahi Pro Tyto Software Pvt. Ltd. 127

Appendix 3: Integrate with Jenkins
Before integration, you will first need an Ant target to run the suite file. Save this code snippet in Sahis
root folder as jenkins-sample.xml.
<project name="demo" default="ff">
<property name="userdata.dir" value="${basedir}/userdata"/>
<property environment="env" />
<property name="urlbase" value="sahi.co.in"/>
<taskdef name="sahi" classname="net.sf.sahi.ant.RunSahiTask" classpath="lib/ant-sahi.jar"/>
<target name="ff" description="start the server and run sahi tests">
<parallel>
<sequential>
<waitfor maxwait="3" maxwaitunit="minute" checkevery="100">
<http url="http://localhost:9999/logs/"/>
</waitfor>
<antcall target="runfftests"/>
<antcall target="stopsahi"/>
</sequential>
<antcall target="start"/>
</parallel>
</target>

<target name="runfftests">
<sahi suite="../userdata/scripts/demo/demo.suite "
browserType="firefox"
baseurl="http://${urlbase}/demo/"
sahihost="localhost"
sahiport="9999"
failureproperty="sahi.failed"
haltonfailure="false"
userDefinedId="sahi.co.in_firefox_english"
threads="6">
<customfield key="language" value="english"/>
<report type="junit" logdir="${userdata.dir}/temp/junit/tests"/>
</sahi>
<antcall target="report-gen"/>
<antcall target="failsahi"/>
</target>

<target name="report-gen">
<delete dir="${userdata.dir}/temp/junit/reports/sahi-html">
</delete>
<mkdir dir="${userdata.dir}/temp/junit/reports" />
<junitreport todir="${userdata.dir}/temp/junit/reports">
<fileset dir="${userdata.dir}/temp/junit/tests/junit">
<include name="TEST-*.xml" />
</fileset>
<report format="frames" todir="${userdata.dir}/temp/junit/reports/sahi-html" />
</junitreport>
</target>



Sahi Pro Tyto Software Pvt. Ltd. 128

<target name="start" description="starts proxy">
<java classname="net.sf.sahi.Proxy" fork="true">
<classpath location="lib/sahi.jar">
<pathelement location="extlib/rhino/js.jar"/>
<pathelement location="extlib/apc/commons-codec-1.3.jar"/>
<pathelement location="extlib/license/truelicense.jar"/>
<pathelement location="extlib/license/truexml.jar"/>
<pathelement location="extlib/db/h2.jar" />
<fileset dir="extlib" includes="*.jar"/>
</classpath>
<arg value="." id="basePath"/>
<arg value="userdata" id="userdataPath"/>
</java>
</target>

<target name="stopsahi" description="stop sahi server">
<sahi stop="true" sahihost="localhost" sahiport="9999"/>
</target>

<target name="failsahi" if="sahi.failed">
<fail message="Sahi tests failed!"/>
</target>
</project>

Let us assume that Jenkins is available in C:\.jenkins\
To run this Ant target from Jenkins, follow these steps.
From the Jenkins dashboard, click on "New job".
Enter job name as "SahiPro" (This will be the name of the job identified by Jenkins.)
Select Build a free-style software project . Click OK.
You should see a folder by name "SahiPro" when you navigate to C:\.jenkins\jobs from the file
explorer
You should then be directed to the Configure page. Click on "Add build step". Select "invoke
Ant"
Type "-f jenkins-sample.xml ff"
In "Post Build Actions", check " Publish JUnit test result report" and add this in the textbox
"userdata/temp/junit/reports/*.xml"
Click Save.
On the left menu, click Build now. This will create a workspace for your project. NOTE: The build
will fail, but that is fine.
Now, if Sahi Pro is installed in C:\SahiPro, navigate to that folder on your explorer. Copy all the
contents inside C:\SahiPro and paste it in "C:\.jenkins\jobs\SahiPro\workspace". Your workspace
folder should now look like C:\SahiPro
Now, on the Jenkins dashboard, click "Build now".


Sahi Pro Tyto Software Pvt. Ltd. 129

After the tests have run, you will be able to see "Latest Test Result" on the Project home page.
Click on it to view your results.

You should have all the reports created at this point.


INFO:
This target runs a suite file called demo.suite available in SahiPro\userdata\scripts\demo. This
uses http://sahi.co.in/demo/ as the start URL. Hence you see that a property called "urlbase"
has a value "sahi.co.in". This is the base url.
Jenkins tries to look for reports in the workspace root folder. Please look at a target called
"report-gen" in jenkins-sample.xml. You can generate the report in any directory. You will have
to be familiar with the Ant <junitreport/> task to achieve this.
While specifying the target in "Add build step", it is possible to specify the path to ANY Ant build
file.
Eg. if you say ant -f C:\sahi_pro\demo.xml all, Ant will run the target "all" in demo.xml
You CAN customize a test to run from Jenkins without moving Sahi into the workspace.
Familiarity of Jenkins and Ant is necessary to achieve this.







Sahi Pro Tyto Software Pvt. Ltd. 130

Appendix 3: Configuring Sahi with Xvfb
It is sometimes good to run tests headless (without a user interface). It is faster and allows the user to
perform other tasks on the computer, while the tests are being run in background. On linux systems,
Firefox can be configured to use Xvfb to run Sahi tests in headless mode.
What is xvfb?
From wikipedia (http://en.wikipedia.org/wiki/Xvfb): Xvfb or X virtual framebuffer is an X11 server that
performs all graphical operations in memory, not showing any screen output. From the point of view of
the client, it acts exactly like any other server, serving requests and sending events and errors as
appropriate. However, no output is shown. This virtual server does not require the computer it is
running on to even have a screen or any input device. Only a network layer is necessary.
Installing Xvfb:
For ubuntu, run apt-get install Xvfb
For Fedora, run yum install Xvfb
For other linux,
Download xvfb.tgz from http://ftp.xfree86.org/pub/XFree86/4.6.0/binaries/FreeBSD-4.x/
Let us consider that the downloaded file is at ~/Downloads.
cd /
tar xvf ~/Downloads/xvfb.tgz
cd /usr
sudo mkdir X11R6
sudo cp ~/Downloads/xvfb/*.* /usr/X11R6/
chmod +x bin/Xvfb
cd bin
Create a new file Xvfb and add the script below,
















Sahi Pro Tyto Software Pvt. Ltd. 131

#!/bin/sh
mode=$1
case "$mode" in
'start')
if [ -f /usr/X11R6/bin/Xvfb ]; then
echo "***Starting up the Virtual Frame Buffer on Screen 1***"
/usr/X11R6/bin/Xvfb :1 -screen 0 1152x900x8 &
fi
;;
*)
echo " Usage: "
echo " $0 start (start XVFB)"
echo " $0 stop (stop XVFB - not supported)"
exit 1
;;
esac
exit 0
chmod +x Xvfb
Setting up Xvfb on display 1:
export DISPLAY=:1.0 firefox
startx -- `which Xvfb` :1 -screen 0 1024x768x24
Running test in Xvfb headless browser through Sahi:
Configure sahi/userdata/config/browser_types.xml to have browser entries as below,

<browserType>
<name>firefox-xvfb</name>
<displayName>Firefox</displayName>
<icon>firefox.png</icon>
<path>env DISPLAY=:1 firefox</path>
<options>-profile "$userDir/browser/ff/profiles/sahi$threadNo" -no-remote</options>
<processName>firefox</processName>
<capacity>5</capacity>
</browserType>

or Click on Configure link on Dashboard, and add the above entries before the ending
</browserTypes> tag in browser_types.xml
Save and restart Sahi.
To run a test in Xvfb: navigate to sahi/userdata/bin on terminal and run the command:
testrunner.sh demo/sahi_demo.sah http://sahi.co.in/demo/ firefox-xvfb



Sahi Pro Tyto Software Pvt. Ltd. 132

Appendix 4: Reading XML with Sahi

Sahi uses Rhino as its javascript engine and Rhino has excellent support for handling XML.
Below is a script which reads and asserts XML nodes and attributes. The example has been picked from
http://www.ibm.com/developerworks/webservices/library/ws-ajax1/ so that it is easy to experiment
with the ibm examples in this script.
<people>
<person gender="male">
<name>Ant</name>
<hair>Shaggy</hair>
<eyes>Blue</eyes>
<height measure="metric">176</height>
</person>
<person gender="male">
<name>Paul</name>
<hair>Spiky</hair>
<eyes>Grey</eyes>
<height measure="metric">178</height>
</person>
</people>
var $x = new XML(xmlStr);
_assertEqual("Ant", $x.person[0].name.toString());
_assertEqual("Grey", $x.person[1].eyes.toString());

for each (var $p in $x.person){
var $measure = $p.height.@measure.toString();
_assert($measure == "metric");
_assert($p.height > 170);
}


Note:
1. All nodes that you access are of type xml. You will need to use toString() on them before you
assert them.
2. Using @ from inside a Browser Action Function (like _click, _assert etc.) causes the script to fail
because of a parsing error in Sahi's code. So first assign it to a variable and then use it, like it has
been used for $measure. This bug will be fixed in the coming release.
References:
http://www.ibm.com/developerworks/webservices/library/ws-ajax1/
http://www.xml.com/pub/a/2007/11/28/introducing-e4x.html




Sahi Pro Tyto Software Pvt. Ltd. 133

Appendix 5: Troubleshooting Sahi Pro
My Dashboard does not show all installed browsers:
Open <SAHI_HOME>/userdata/config/browser_types.xml . The paths of the browsers should match the
browser location on your machine. If you have a custom browser which is not available there, you can
add your own too.
A typical syntax is:
<browserTypes>
<browserType>
<name>firefox</name>
<displayName>Firefox</displayName>
<icon>firefox.png</icon>
<path>$ProgramFiles\Mozilla Firefox\firefox.exe</path>
<options>-profile "$userDir/browser/ff/profiles/sahi$threadNo" -no-remote</options>
<processName>firefox.exe</processName>
<capacity>5</capacity>
</browserType>
</browserTypes>

name key by which this browserType will be referred
displayName Text visible on the Sahi Dashboard
icon png icon. These are bundled inside Sahi
path path to browser executable. If you run this from a command line, it should invoke
the browser
options options needed by browser. Generally this sets the proxy, and isolates browser
sessions so that cookies are not shared.
processName the processName for looking up PID of process. Sahi will do a tasklist or ps with
this name to identify the process to kill
capacity maximum number of browsers simultaneously executable without overwhelming
the system. This depends on your system and you can configure this based on your
judgement
useSystemProxy true/false Specifies if Windows system proxy settings should be changed to use
Proxy. Needed by Internet Explorer and Safari on Windows
force true/false Sahi checks to see that the path attribute above is correct and
available on the system. On some OSes the path is not really a file path but a
command to invoke the browser. Use force=true in those cases
If your browser is installed in a non standard directory, edit sahi/userdata/browser_types.xml and set
the correct path.
Alternately, you can click on Configure link on the Sahi Dashboard and edit browser_types.xml.
Sahi needs to be restarted for the settings to take effect.


Sahi Pro Tyto Software Pvt. Ltd. 134

Sahi comes with default configurations for various browsers and operating systems. These are available
in sahi/config/browser_types directory. If sahi/userdata/config/browser_types.xml file is deleted, the
correct file will be replaced from the defaults.
Default browser configurations for various operating systems:
win32.xml win64.xml linux.xml mac.xml

I am unable to access HTTPS/SSL sites on IE.
Sahi Pro eases the pain by automatically accepting SSL certificates. Sahi ships with a root certificate and
all other certificates will be signed by this root certificate, making SSL testing absolutely smooth.
But, for some reason if the browser reports a certificate error as shown below, then you will need to
import the root certificate to the Trusted Root Certificate Authorities store.

To import the root certificate, click on the SSL link on dashboard.
1. Sahi first tries to import the certificate with certutil command available on Windows.
2. If Step 1 fails, Sahi then tries to import the certificate through Java. At this point you should be
able to see this screen


Sahi Pro Tyto Software Pvt. Ltd. 135


Click Yes to import the certificate.

3. If Step 2 fails, Sahi will then try a direct import. Follow these steps.



Sahi Pro Tyto Software Pvt. Ltd. 136




1
2
3
4
5


Sahi Pro Tyto Software Pvt. Ltd. 137




This should import the certificate successfully.


Sahi Pro Tyto Software Pvt. Ltd. 138

Once done, you should be able to access your HTTPS/SSL site.
My AJAX pages do not render correctly when navigating through Sahi, or I get
Javascript errors only when going through Sahi.
Sahi controls the browser by injecting javascript into web pages. However, there are various requests
like XMLHttpRequests, javascript, css, etc. where Sahi should not inject its code. While this is correctly
detected and handled in most cases, there are instances where one may need to explicitly ask Sahi not
to inject code. In such instances, regular expression patterns can be added to exclude_inject.txt. When a
URL matches this pattern, Sahi will NOT inject its code.

For example while using ExtJS, Add
.*callback=.*
at the end of sahi/userdata/config/exclude_inject.txt,
restart Sahi, clear browser cache, and it should fix problems with AJAX and extjs.

You could determine the URL patterns using Firebug on Firefox, or using the Developer Tools on Internet
Explorer or Chrome. If none of these work for you, enable traffic logging in Sahi and look at the various
request responses.

To turn on HTTP traffic logging:
Click on Enable Traffic Logs on the dashboard.
All traffic will be written to userdata/logs/traffic folder organized by date.
NOTE: Click on Disable Traffic Logs once you are done, or else the logs will quickly fill your hard disk.
To turn on HTTP traffic logging manually:
1. Open sahi/userdata/config/userdata.properties
2. Add (or edit if already present)
debug.traffic.log.unmodified=true debug.traffic.log.modified=true
3. Restart Sahi.
NOTE: RESET TRAFFIC LOGGING TO FALSE once you are done, or else the logs will quickly fill your hard
disk.

Look at response.body_unmodified_xxx and response.body_modified_xxx to see if Sahi has injected
code into the file. If yes, add the URL pattern to exclude_inject.txt Note that the pattern needs to be a
proper regular expression which will match the whole url.
If your url is http://myapp/myajaxrequests.jsp?action=add,
Your regex may look like .*myajaxrequests[.]jsp.*

To explain, . (dot) means any character, *(asterisk) means any number of times, a literal . needs to be
escaped by putting in square brackets. So the previous means, any character any number of times, then
myajaxrequests, then a literal . (dot), then jsp and again any character any number of times)


Sahi Pro Tyto Software Pvt. Ltd. 139

Controller does not identify elements on one website. It works for other
websites.
Do a view source on the page and search for document.domain. You may see something like:
document.domain = "maindomain.com"
This is done by the application developer, so that two frames/iframes from domains like
a.maindomain.com and b.maindomain.com can communicate with each other via javascript.
To make Sahi work correctly with this, open sahi/userdata/config/domainfix.txt and add
*.maindomain.com maindomain.com
Save, restart Sahi, and now the Controller should work correctly.
Playback starts but keeps waiting on some page
Sahi waits on AJAX requests to make sure they are complete, before proceeding with playback. Some
sites keep some AJAX requests open so that they can continuously poll for data. This causes Sahi to
indefinitely wait for those requests to complete.
1. To fix this:
Open sahi/userdata/config/userdata.properties
2. Add (or edit)
xhr.wait_ready_states=2,3
3. Save the file, and restart Sahi
This should fix the issue.
Connecting through VPNs for IE
(This also needs to be done for data cards like Tata Photon, Reliance etc.)
Sahi sets the IE LAN proxy settings to localhost 9999 automatically. When going through a VPN, you do
not use the LAN, so Sahis settings would not work. To fix this you need to
1. Manually configure IE to use Sahi for the VPN connection
2. Optionally, tell Sahi to not change the LAN settings (optional: do this only if you will never
use LAN)
To accomplish this, please follow the instructions below:
1. On IE, go to Tools -> Internet Options -> Connections -> Dial-up and Virtual Private Network
Settings. There choose your VPN, and click on Settings button near it. Set localhost 9999
for HTTP and Secure.
Now Sahi should work correctly over your VPN.
2. (Optional, do this only if you will never use LAN) Open browser_types.xml from the Configure
link on dashboard, and remove
<useSystemProxy>true</useSystemProxy>
line from Internet Explorer settings (You can remove it where ever it is present.)
Save, restart Sahi, and now Sahi will not try to change proxy settings of your system.


Sahi Pro Tyto Software Pvt. Ltd. 140

Appendix 6: Sahi headless execution with PhantomJS
PhantomJS is a headless browser based on WebKit. (A headless browser runs without a user interface)
To run Sahi headless on PhantomJS:
Quick start guide for using PhantomJS with Sahi Pro for load testing:
Download phantomjs-1.x.x-win32-dynamic.zip from
http://code.google.com/p/phantomjs/downloads/list
Unzip phantomjs-1.x.x-win32-dynamic.zip inside sahi/ext/phantomjs/ folder such that you have
sahi/ext/phantomjs/phantomjs.exe
Normal Installation:
1. Download phantomjs-1.x.x-win32-dynamic.zip from
http://code.google.com/p/phantomjs/downloads/list
2. Unzip it to, say C:\phantomjs-1.x.x-win32 such that phantomjs.exe is available at
C:\phantomjs-1.x.x-win32\phantomjs.exe
3. Create a file sahi.js in C:\phantomjs-1.x.x-win32 with the content below:
For version 1.1.0, use:
if (phantom.state.length === 0) {
if (phantom.args.length === 0) {
console.log('Usage: sahi.js <Sahi Playback Start URL>');
phantom.exit();
} else {
var address = unescape(phantom.args[0]);
phantom.state = "sahi script running";
console.log('Loading ' + address);
phantom.open(address);
}
} else {
if (phantom.loadStatus === 'success') {
console.log('Page title is ' + document.title);
} else {
console.log('FAIL to load the address');
}
}
For version 1.2.0 onwards, use:


Sahi Pro Tyto Software Pvt. Ltd. 141

if (phantom.args.length === 0) {
console.log('Usage: sahi.js <Sahi Playback Start URL>');
phantom.exit();
} else {
var address = unescape(phantom.args[0]);
console.log('Loading ' + address);
var page = new WebPage();
page.open(address, function(status) {
if (status === 'success') {
var title = page.evaluate(function() {
return document.title;
});
console.log('Page title is ' + title);
} else {
console.log('FAIL to load the address');
}
});
}

The above code is based on the example provided by PhantomJS
4. Click Configure link on Dashboard, and add
<browserType>
<name>phantomjs</name>
<displayName>PhantomJS</displayName>
<icon>safari.png</icon>
<path> C:\phantomjs-1.1.0-win32\phantomjs.exe</path>
<options>--proxy=localhost:9999 C:\phantomjs-1.1.0-win32\sahi.js</options>
<processName>phantomjs.exe</processName>
<capacity>100</capacity>
<force>true</force>
</browserType>

before the ending </browserTypes> tag in browser_types.xml
5. Save and restart Sahi.
6. To run a test in PhantomJS: Click on Bin on the dashboard (or navigate to sahi/userdata/bin on
a command prompt) and run the command

testrunner.bat demo/sahi_demo.sah http://sahi.co.in/demo/ phantomjs

This will run the Sahi script without opening a browser.

S-ar putea să vă placă și