Sahi

135
Sahi Pro V 4.0 Web Automation and Testing Tool User Manual

Transcript of Sahi

Page 1: Sahi

Sahi Pro V 4.0

Web Automation and Testing Tool

User Manual

Page 2: Sahi

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

Page 3: Sahi

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

Page 4: Sahi

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 ............................................................................................................................... 71

Browser popups: Alerts, Confirms and Prompts................................................................................ 72

Utility functions to access properties of elements ............................................................................. 74

Marker functions to show DOM relation ............................................................................................ 76

Page 5: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 5

Marker functions to show Positional relation .................................................................................... 76

Browser Action APIs .............................................................................................................................................. 77

Mouse Actions .................................................................................................................................... 77

Focus Actions ...................................................................................................................................... 82

Key Actions .......................................................................................................................................... 83

Data Input Actions .............................................................................................................................. 84

Assertions ............................................................................................................................................ 87

Utility actions ...................................................................................................................................... 91

Actions to mock out particular URLs .................................................................................................. 98

Actions to set expectations for javascript confirms and prompts .................................................... 100

Actions used for debugging .............................................................................................................. 101

Toggle KeepAlive Actions .................................................................................................................. 103

Cookie related actions ...................................................................................................................... 103

Download related actions ................................................................................................................. 104

Miscellaneous APIs ............................................................................................................................................... 106

Functions available on browser and on proxy .................................................................................. 106

Functions available on proxy only .................................................................................................... 109

Recovery functions ........................................................................................................................... 111

Working with databases ................................................................................................................... 112

Working with files ............................................................................................................................. 115

Data driven testing ............................................................................................................................ 117

APIs for browser detection ............................................................................................................... 119

APIs for screen capture ..................................................................................................................... 119

Appendix 3: Integrate with Jenkins ..................................................................................................................................... 121

Appendix 3: Configuring Sahi with Xvfb............................................................................................................................ 124

What is xvfb? ........................................................................................................................................................ 124

Installing Xvfb: ..................................................................................................................................................... 124

Setting up Xvfb on display 1: ................................................................................................................................ 125

Running test in Xvfb headless browser through Sahi:........................................................................................... 125

Appendix 4: Reading XML with Sahi .................................................................................................................................... 126

Page 6: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 6

Appendix 5: Troubleshooting Sahi Pro ............................................................................................................................... 127

My Dashboard does not show all installed browsers: ........................................................................................... 127

I am unable to access HTTPS/SSL sites on IE. ..................................................................................................... 128

My AJAX pages do not render correctly when navigating through Sahi, or I get Javascript errors only when going

through Sahi. ......................................................................................................................................................... 132

Controller does not identify elements on one website. It works for other websites. ............................................. 133

Playback starts but keeps waiting on some page ................................................................................................... 133

Connecting through VPNs for IE .......................................................................................................................... 133

Appendix 6: Sahi headless execution with PhantomJS ................................................................................................ 134

Quick start guide for using PhantomJS with Sahi Pro for load testing: ................................................................. 134

Normal Installation: ............................................................................................................................................... 134

Page 7: Sahi

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

Page 8: Sahi

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, Sahi’s 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.

Page 9: Sahi

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.

Page 10: Sahi

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:

Page 11: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 11

Page 12: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 12

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

Page 13: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 13

Page 14: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 14

Page 15: Sahi

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 browser’s 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

Page 16: Sahi

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

Page 17: Sahi

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)

Page 18: Sahi

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

Page 19: Sahi

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

Page 20: Sahi

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.

Page 21: Sahi

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.

Page 22: Sahi

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

Page 23: Sahi

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

Page 24: Sahi

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>

Page 25: Sahi

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

Page 26: Sahi

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.

Page 27: Sahi

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>

Page 28: Sahi

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 sahi’s root folder in demo.xml

Page 29: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 29

Sahi Pro Controller

Recorder Tab

Page 30: Sahi

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.

Page 31: Sahi

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.

Page 32: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 32

Save the script once done.

Page 33: Sahi

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

Page 34: Sahi

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

Page 35: Sahi

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.

Page 36: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 36

Database Report

Page 37: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 37

Suite Report

Script Report

Page 38: Sahi

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.

Page 39: Sahi

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 */

Page 40: Sahi

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 page’s 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 page’s 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

Page 41: Sahi

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");

Page 42: Sahi

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 == "[email protected]"){ _setValue(_password("pwd"), "secret"); }

Using custom functions that access the DOM. Custom functions which access the browser’s 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("[email protected]", 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 browser’s DOM.

Prefix a $ sign before variables which are passed to sahi functions. var $name = "karthik"; _setValue(_textbox("userName"), $name); Note that $name’s value “karthik” is independent of any page.

Page 43: Sahi

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. }

Page 44: Sahi

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.

Page 45: Sahi

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"));

Page 46: Sahi

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:

Page 47: Sahi

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.

Page 48: Sahi

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.

Page 49: Sahi

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

Page 50: Sahi

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:

Page 51: Sahi

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"

Page 52: Sahi

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

Page 53: Sahi

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.

Page 54: Sahi

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.

Page 55: Sahi

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. Sahi’s Controller window will pop up. You can now start recording your Flex application. NOTE:

Ctrl + hover (to get a flex element’s 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")

Page 56: Sahi

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)

Page 57: Sahi

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.

Page 58: Sahi

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 either be a numerical index or a property as specified in each case.

Identifiers which are not numerical can either be a string or a javascript regular expression.

Identifiers which are strings can also have an index along with them in square brackets as part of

the string.

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 13th 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

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> </tr> </table>

Page 59: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 59

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

_link("delete") points to the first delete link. This is the 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.

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

_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”

Page 60: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 60

Positional Relations

_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:

_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

Page 61: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 61

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");

API _span(identifier[, domRelation])

HTML <span id="id">text</span>

Identifier Index,id,text

Example _span("text");

Page 62: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 62

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");

API _heading5(identifier[, domRelation])

HTML <h5 id=”id”>text</h5>

Identifier text, id

Example _heading5("text");

Page 63: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 63

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");

API _code(identifier[, domRelation])

HTML <code class="className" id="id">sahiText </code>

Identifier sahiText, id, className, index

Example _code("sahiText");

Page 64: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 64

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");

API _preformatted(identifier[, domRelation])

HTML <pre class="className" id="id">sahiText</pre>

Identifier sahiText, id, className, index

Example _preformatted("sahiText");

Page 65: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 65

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 value“value11”

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");

Page 66: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 66

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");

API _radio(identifier[, domRelation])

HTML <input type="radio" name="name" id="id" value="value">

Identifier id, name, value, className, index

Example _radio("id");

Page 67: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 67

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");

API _select(identifier[, domRelation])

HTML <select name="name" id="id"></select>

Identifier name, id, index, className

Example _select("id");

Page 68: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 68

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");

API _datetimebox(identifier)

HTML <input type="datetime" name="name" id="id" value="value"/>

Identifier name, id, index, className

Example _datetimebox("name");

Page 69: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 69

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");

API _telephonebox(identifier)

HTML <input type="tel" name="name" id="id" value="value"/>

Identifier name, id, index, className

Example _telephonebox("name");

Page 70: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 70

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 nth 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");

API _parentCell(element[, occurrence])

HTML <td id="id"><a href=" http://u/r/l ">aElement</a></td>

Example _parentCell(_link("aElement"));

Page 71: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 71

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");

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");

Page 72: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 72

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 Sahi’s 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");

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.

Page 73: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 73

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.

API _printCalled()

Notes Returns true if window.print() had been invoked

Example _printCalled();

Page 74: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 74

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 element’s 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”

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

Page 75: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 75

API _rteHTML(element)

Notes Returns the html inside a rich text editor.

Example _rteHTML(_rte("rteId")); will return the rich text editor’s contents.

API _rteText(element)

Notes Returns the text inside a rich text editor.

Example _rteText(_rte("rteId")); will return the rich text editor’s 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"));

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"));

Page 76: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 76

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)

Notes Refer “Positional Relations”

Page 77: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 77

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

Page 78: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 78

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

Page 79: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 79

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

Page 80: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 80

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);

Page 81: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 81

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

Page 82: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 82

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 element’s 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 element’s 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

Page 83: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 83

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

Page 84: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 84

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

Page 85: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 85

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: Option’s 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

Page 86: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 86

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 form’s action URL is changed on setting the file. By default, it uses the form’s 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 field’s 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.

Page 87: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 87

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

Page 88: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 88

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.

Page 89: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 89

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.

Page 90: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 90

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"));

Page 91: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 91

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);

Page 92: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 92

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

Page 93: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 93

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.

Page 94: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 94

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 Sahi’s 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);

Page 95: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 95

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 Sahi’s classpath: Look at Adding jars to Sahi’s 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.

Page 96: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 96

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.

Page 97: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 97

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

Page 98: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 98

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.MyCustomMock’s filterAds method.

One can call any class’s 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

Page 99: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 99

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

Page 100: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 100

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

Page 101: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 101

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

Page 102: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 102

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");

Page 103: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 103

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

Page 104: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 104

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.

Sahi’s 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.

Page 105: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 105

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

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

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

Page 106: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 106

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

Page 107: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 107

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.

Page 108: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 108

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

Page 109: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 109

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();

Page 110: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 110

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

Page 111: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 111

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.

Page 112: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 112

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."); // 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. _removeRecovery(myRecoveryFn);

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 Sahi’s external classpath.

More info: Adding jars to Sahi’s 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");

Page 113: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 113

$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).

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

You can also connect to an excel sheet with _getDB.

Page 114: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 114

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.

Page 115: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 115

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 file’s contents.

Syntax _readFile( filePath ) filePath: Path of file to read. Paths are relative to the script’s 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 script’s 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 script’s 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

Page 116: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 116

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 script’s 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 script’s 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 script’s location. Specify absolute path if the file should be deleted from any other path.

Example _deleteFile("sahicsv.txt");

Page 117: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 117

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); }}

Page 118: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 118

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] ]

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 function doAdd($first, $second, $total){ _setValue(_textbox("first"), $first); _setValue(_textbox("second"), $second); _click(_button("Add")); _assertEqual($total, _textbox("total").value); } 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()

Page 119: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 119

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

Page 120: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 120

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

Page 121: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 121

Appendix 3: Integrate with Jenkins Before integration, you will first need an Ant target to run the suite file. Save this code snippet in Sahi’s

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>

Page 122: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 122

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

Page 123: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 123

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.

Page 124: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 124

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,

Page 125: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 125

#!/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

Page 126: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 126

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 = [email protected](); _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

Page 127: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 127

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.

Page 128: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 128

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. You can create a single trusted root

certificate for your organization and all other certificates will be signed by your trusted 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

Page 129: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 129

Click “Yes” to import the certificate.

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

Page 130: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 130

1

2

3

4 5

Page 131: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 131

This should import the certificate successfully.

Page 132: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 132

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. If neither of these works 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)

Page 133: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 133

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 Sahi’s 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.

Page 134: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 134

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:

Page 135: Sahi

Sahi Pro © Tyto Software Pvt. Ltd. 135

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.