Вы находитесь на странице: 1из 135

Sahi Pro V 4.

0
Web Automation and Testing Tool User Manual

Contents
Sahi - Introduction .............................................................................................................................................................................7
Sahi Architecture ....................................................................................................................................................... 8

Sahi Advantages ..................................................................................................................................................................................9


Browser Platform Independence ............................................................................................................................... 9 Smart Identification Mechanisms .............................................................................................................................. 9 UI Relations .............................................................................................................................................................. 9 Parallel Playback ....................................................................................................................................................... 9

Getting Started .................................................................................................................................................................................. 10


Prerequisites ............................................................................................................................................................ 10 Download Sahi Pro.................................................................................................................................................. 10 Installation of Sahi .................................................................................................................................................. 10

Starting Sahi ...................................................................................................................................................................................... 15 Recording through Sahi ................................................................................................................................................................ 16 Playing back through Sahi .......................................................................................................................................................... 21
Running a test from the controller ........................................................................................................................... 21 View Logs ............................................................................................................................................................... 22

Creating a Suite File ....................................................................................................................................................................... 23


Running a test or suite from command line ............................................................................................................. 24 Running a test or suite using ant: ............................................................................................................................ 25

Distributing tests across different machines using ant: ..................................................................... 26 Load testing using ant: ........................................................................................................................ 27 Sahi Pro Controller.......................................................................................................................................................................... 29
Recorder Tab ........................................................................................................................................................... 29 The Anchor Button .................................................................................................................................................. 30

Example............................................................................................................................................... 30
Using the Sahi Script Editor .................................................................................................................................... 31

Sahi Pro

Tyto Software Pvt. Ltd.

Playback Tab ........................................................................................................................................................... 33

Running Tests on multiple machines ...................................................................................................................................... 34


Reports .................................................................................................................................................................... 35 Database Report ...................................................................................................................................................... 36

Sahi Scripting Basics ...................................................................................................................................................................... 39


Statements: .............................................................................................................................................................. 39 Variable declaration: ............................................................................................................................................... 39 Function declaration: ............................................................................................................................................... 39 Comments: .............................................................................................................................................................. 39 if statements: ........................................................................................................................................................... 40 for loops: ................................................................................................................................................................. 40 while loops: ............................................................................................................................................................. 41 Including another Sahi script file: ........................................................................................................................... 41

Advanced Scripting ......................................................................................................................................................................... 42


Perform all actions using Browser Action APIs. ..................................................................................................... 42 Use _set to store a variable with data from browser ................................................................................................ 42 Using custom functions that access the DOM. ........................................................................................................ 42 Prefix a $ sign before variables which are passed to sahi functions. ....................................................................... 42

Exception Handling using try-catch........................................................................................................................................ 43 Recovering without try-catch using _setRecovery............................................................................................................ 44 Script Lifecycle Call Back Functions........................................................................................................................................ 45 Sahi Pro Excel Framework .......................................................................................................................................................... 46
Sample Excel Sheet ................................................................................................................................................. 46 Loading Sahi script libraries .................................................................................................................................... 46 Executing the Excel Sheet ....................................................................................................................................... 47 Play back reports/logs ............................................................................................................................................. 47

IMPORTANT NOTES ............................................................................................................................ 48 Sahi Pro Tyto Software Pvt. Ltd. 3

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 Sahi Pro Tyto Software Pvt. Ltd. 4

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 Sahi Pro Tyto Software Pvt. Ltd. 5

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

Sahi Pro

Tyto Software Pvt. Ltd.

Sahi - Introduction
Sahi is an automation tool to test web applications. Sahi injects javascript into web pages using a proxy and the javascript helps automate web applications. Sahi is a tester friendly tool. It abstracts out most difficulties that testers face while automating web applications. Some salient features include: Excellent recorder Platform and browser independence No XPaths No waits Multithreaded (parallel) playback Excellent Java interaction Inbuilt reporting

Sahi Pro builds on Sahi Open Source to add significant time saving features. Sahi Pro adds the ability to: Spread playback across multiple machines Edit scripts and create functions right from the Controller Build object repositories automatically while recording Automatically accept SSL certificates Automate your flex components with sfl - Sahi Flex (Beta) Compare logs and screenshots to compare the outcomes of scripts run on different browsers Customize your logs as XML, HTML or directly feed them to a database. Modify XSL style sheets to get custom reporting according to your needs. Use inbuilt Excel based Framework which lets non-technical users participate in automation

Sahi Pro

Tyto Software Pvt. Ltd.

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

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

Both these technologies are basic building blocks of internet technologies and will necessarily be supported by all browsers, making Sahi very easily extensible to newer browsers or newer versions of browsers.

Sahi Pro

Tyto Software Pvt. Ltd.

Sahi Advantages
Sahi is an engineering solution for an engineering problem. We use heuristics based algorithms, fuzzy logic, thresholds etc. to arrive at a solution which is 99.9% correct. Sahi also exposes the ability to be exact when needed, making Sahi very suitable for any web application.

Browser Platform Independence


Sahi, because of its architecture, supports any browser with javascript support and any Operating System with Java support

Smart Identification Mechanisms


The Javascript DOM exposes a lot of properties of various elements on the browser. Sahi uses these different properties to identify elements. One significant point is that Sahi gives the visible text a higher priority than other code related properties like css style. This helps in two ways Writing and maintaining test scripts become very easy. What you see is what you script. It validates what a user sees and not what a developer coded.

Sahi automatically goes through frames, iframes etc. to find elements. One does not need to explicitly select a frame in the automation script. So if developers moved the login fields into an iframe, Sahi will still work with your older scripts.

UI Relations
Sahi is slightly different from other automation technologies. It relies less on the underlying code and more on the business intention of the user interface. Code changes are frequent in an evolving application and relying on business intention is a more stable way of writing automation test cases. Sahi does this through what is called UI Relations. UI Relations help identify one element with respect to another element which communicates strong business intention. For example: The cost of "Laptop" in a tabular structure may be represented in Sahi as _cell(0, _near(_div("Laptop")), _under(_div("Cost"))) This represents the cell which is near "Laptop" and under "Cost". Note that even if there are more columns or rows added in that grid structure, this always points to the correct cell. If we had used the column index or row index, the test would break as soon as the location of Laptop or Cost changed.

Parallel Playback
Sahi allows Parallel or Multithreaded playback. Multiple tests can be run simultaneously to reduce playback time, thus reducing your build time and shortening your feedback cycle. One can also spread the tests across machines or on the cloud and get one consolidated report, all stored in a database.

Sahi Pro

Tyto Software Pvt. Ltd.

Getting Started
Prerequisites
Java 1.5 or above is needed for running Sahi.

Download Sahi Pro


Download Sahi Pro from http://sahi.co.in/w/download-sahi-pro

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

Sahi Pro

Tyto Software Pvt. Ltd.

10

Sahi Pro

Tyto Software Pvt. Ltd.

11

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

Sahi Pro

Tyto Software Pvt. Ltd.

12

Sahi Pro

Tyto Software Pvt. Ltd.

13

Sahi Pro

Tyto Software Pvt. Ltd.

14

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

Sahi Configuration

Opens the Scripts folder in a file explorer

Root certificate importer

Opens a terminal at userdata/bin folder

Turn On (Off) HTTP Traffic Logging

HTML based results stored in database

If the browsers are not visible on Dashboard, look here for trouble shooting: http://sahi.co.in/w/trouble-shooting-sahi Sahi Pro Tyto Software Pvt. Ltd. 15

Recording through Sahi


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

Sahi Pro

Tyto Software Pvt. Ltd.

16

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

Sahi Pro

Tyto Software Pvt. Ltd.

17

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

All recorded steps are visible in the Recorded Steps box

Sahi Pro

Tyto Software Pvt. Ltd.

18

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

Press CTRL key and Hover mouse

o o

Click the Assert button to generate assertions for the element. They will appear in the Evaluate Expression box. 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. Once satisfied, click on Append to Script. This will add the assertions to the script.

Click Stop to finish recording. Tyto Software Pvt. Ltd. 19

Sahi Pro

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

Sahi Pro

Tyto Software Pvt. Ltd.

20

Playing back through Sahi


Running a test from the controller
Open the Sahi controller (ALT-Dbl click on the page). Click on Playback tab Enter the script name in the File: field (with the help of the auto completion feature) Enter the start URL of the test. Eg. If you had started recording from http://sahi.co.in/demo/training/, use that URL. Click Set. Wait for the page to reload. Click Play.

Steps will start executing, and the controller will be updated accordingly. Once finished, SUCCESS or FAILURE will be displayed at the end of the steps.

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

Sahi Pro

Tyto Software Pvt. Ltd.

21

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

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

Sahi Pro

Tyto Software Pvt. Ltd.

22

Creating a Suite File


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

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

Sahi Pro

Tyto Software Pvt. Ltd.

23

Running a test or suite from command line


The following command is used to run a test from a command line. Command:
testrunner.bat <sah file|suite file> <startURL> <browserType> <tags>

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

Sahi Pro

Tyto Software Pvt. Ltd.

24

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

Nested Elements report Sahi Pro Specifies type and location of report types can be junit html tm6 Tyto Software Pvt. Ltd. No 25

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>

Attribute suite browserType baseurl sahihost sahiport failureproperty haltonfailure

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

Required Yes Yes Yes Yes Yes Yes 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 host port Description Name or IP Address of the machine Port where Sahi is running on the remote machine Required Yes Yes

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

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

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

Sahi Pro

Tyto Software Pvt. Ltd.

27

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

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

Sahi Pro

Tyto Software Pvt. Ltd.

28

Sahi Pro Controller


Recorder Tab

Sahi Pro

Tyto Software Pvt. Ltd.

29

The Anchor Button


The Anchor button Usage: 1. 2. 3. 4. CTRL - Mouse over Element1 on browser Click the Anchor button CTRL - Mouse over Element2 on browser. Element2 will be resolved relative to Element1 on the Recorder helps in identifying one element relative to another.

Example Suppose we need to identify the third textbox in the UI below

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

Then we click the Anchor button

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

Sahi Pro

Tyto Software Pvt. Ltd.

30

Using the Sahi Script Editor


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

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

Sahi Pro

Tyto Software Pvt. Ltd.

31

Save the script once done.

Sahi Pro

Tyto Software Pvt. Ltd.

32

Playback Tab
Playback Tab

Click for browser, OS and java related information

Enter the script name Recorder Tab

Set the script for playback

Enter the start URL of the script

Click to play the script

Next step to execute. Changing this value, will cause Sahi to skip steps till this.

Click to pause the script

Resets the script to play from 0

View played back steps and status

Click to stop the script

A copy of the test script currently loaded for play back is displayed in the web browser.

Click to step through the script, one step at a time

Displays the actual code that will be executed by Sahi

The browser scripts included in the Sahi script

HTML based results of tests

Sahi Pro

Tyto Software Pvt. Ltd.

33

Running Tests on multiple machines


Sahi can distribute and run tests on multiple machines (nodes) Configuration: 1) Sahi needs to be running on each machine 2) Browser paths need to be correctly specified in browser_types.xml on each node. Refer http://sahi.co.in/w/browser-types-xml for more details on how to configure browser_types.xml Once Sahi is started on all nodes, a suite can be run using this ant target:
<taskdef name="sahid" classname="in.co.sahi.ant.DAntRunner" classpath="lib/ant-sahi.jar" /> <target name="drun"> <tstamp> <format property="ts" pattern="yyyy_MM_dd_HH_mm_ss" locale="en, IN" /> </tstamp> <property name="tempdest" value="scritps/${ts}" /> <sahid suite="${tempdest}/demo/demo.suite" baseurl="http://${urlbase}/demo/" sahihost="localhost" sahiport="9999" failureproperty="sahi.failed" haltonfailure="false" browserType="firefox"> <sync originFolder="userdata/scripts" destFolder="${tempdest}" ignorePattern=".*(svn|copied).*" /> <node host="localhost" port="9999" /> <node host="machine1" port="9999" /> <node host="machine2" port="9999" /> </sahid> <antcall target="failsahi" /> </target>

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

Sahi Pro

Tyto Software Pvt. Ltd.

34

Reports
All reports are logged into the database by default. They can also be logged into the filesystem based on settings in sahi.properties or userdata.properties reports.filesystem.html.enabled=true reports.filesystem.xml.enabled=true reports.db.enabled=true reports.sql.enabled=true # Database logging. # Tables are created using sahi/user data/config/db/create_report_tables.sql db.driver_name=org.h2.Driver db.jdbc_url=jdbc:h2:$userDir/database/db0;DB_CLOSE_DELAY=-1 db.user_name=sa db.password= db.script_gen_xsl=$userDir/config/db/script_sql_gen.xsl

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

Sahi Pro

Tyto Software Pvt. Ltd.

35

Database Report

Sahi Pro

Tyto Software Pvt. Ltd.

36

Suite Report

Script Report

Sahi Pro

Tyto Software Pvt. Ltd.

37

Log comparison (via Compare Logs link)

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

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

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 var $username = "SahiTestUser"; var $password; // declaration; $password = $username + "_password"; // "SahiTestUser_password" All variables start with a $. The keyword var is used for local variables.

Example

Note

Function declaration:
Syntax function functionName($parameter1, $parameter2) { // statements } //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");

Example

Comments:
// This is a single line comment /* This is a multiline comment. This has two lines */ Sahi Pro Tyto Software Pvt. Ltd. 39

if statements:
Syntax if (condition) { // statements } if ($username == "PartnerUser"){ _click(_link("Partner Login")); } If the if condition is page dependent, use if (_condition(booleanExpression)) For example, if (document.loginForm.userName =="karthik"){...} should be written as if (_condition(document.loginForm.userName == "karthik")){...} NOTE _condition need not be added if the condition does not depend on any pages DOM.

Example

for loops:
Syntax for (var $i=0; $i<$max; $i++){ // statements } // 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(); } Do not use a condition which depends on a pages DOM. for (var $i=0; $i<document.links.length; $i++) {...} //WRONG If you want to iterate over page DOM variable, first take a snapshot of it using _set, and then use the variable. For example, <browser> var $anchors = []; function getLinkIds(){ var retVal = []; var links = document.links; for (var i=0; i<links.length; i++){ retVal[i] = links[i].innerHTML; } return retVal; } </browser> _set ($anchors, getLinkIds()); for (var $i=0; $i<$anchors.length; $i++) {...} //RIGHT Sahi Pro Tyto Software Pvt. Ltd. 40

Example

Note

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

Including another Sahi script file:


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

Sahi Pro

Tyto Software Pvt. Ltd.

41

Advanced Scripting
While Sahi scripts can easily be recorded, as a project grows in size, the scripts may have to be more logically organized into functions and split into multiple files. The following section gives more details on the Sahi Script and the rules to follow. Sahi script is based on Javascript. The constructs of javascript, like functions, variables, loops, conditional statements etc. are all available in Sahi script. But the script is parsed and transformed slightly in the Sahi proxy server before execution. To keep matters simple, follow these rules.

Perform all actions using Browser Action APIs.


For example, Use _click(_link("Click Me")) instead of _link("Click Me").click() Use _setValue(_textbox("tb"), "value") instead of _textbox("tb").value = "value"

Use _set to store a variable with data from browser


var $email1 = null; _set($email1, _textbox("email1").value); if ($email1 == "a@sahi.example.com"){ _setValue(_password("pwd"), "secret"); }

Using custom functions that access the DOM.


Custom functions which access the browsers DOM to say, identify a particular element, need to be wrapped in a <browser></browser> tag. For example, <browser> function getEmailValue(){ return _textbox("email").value; } </browser> _assertEqual("a@sahi.example.com", getEmailValue()); A general tip is to always call a browser based function from inside a Browser Action API. Otherwise they will be executed on the proxy and will fail because they do not have access to the browsers DOM.

Prefix a $ sign before variables which are passed to sahi functions.


var $name = "karthik"; _setValue(_textbox("userName"), $name); Note that $names value karthik is independent of any page.

Sahi Pro

Tyto Software Pvt. Ltd.

42

Exception Handling using try-catch


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

Sahi Pro

Tyto Software Pvt. Ltd.

43

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. 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. The recovery function can be removed via _removeRecovery(); Also refer: Recovery functions

Sahi Pro

Tyto Software Pvt. Ltd.

44

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 Notes Function Notes Function Notes onScriptFailure() Is called whenever an assertion failure occurs in the script. onScriptError() Is called whenever an error occurs in the script. onScriptEnd() Is called at the end of a script (even if there are errors in the script and the script stops in the middle).

For example, function onScriptEnd(){ _click(_button("Logout")); } function onScriptError(){ _alert(">> In onScriptError"); } function onScriptFailure(){ _alert(">> In onScriptFailure"); } _navigateTo("http://sahi.co.in/demo/training/"); _setValue(_textbox("user"), "test"); _setValue(_password("password"), "secret"); _click(_submit("Login"));

Sahi Pro

Tyto Software Pvt. Ltd.

45

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 loadSahi Argument1 "books_lib.sah" Argument2 Argument3

Check shopping cart total

[Documentation] login addBooks verifyTotal logout

Smoke test for add books "test" "secret" 3 2 1640

Test login error message

[Documentation] login verifyNotLoggedIn verifyErrorMessage

Checks Invalid login message "test" "bad password" "Invalid username or password"

These tests talk mostly in the language of the business (also called a Domain Specific Language or DSL for that business), and hide away all the implementation details of clicking buttons and populating textboxes.

Loading Sahi script libraries


The implementation details are moved into an included Sahi script, which is linked to this Excel sheet via the initial loadSahi "books_lib.sah" statement.

The code in books_lib.sah is given below: Sahi Pro Tyto Software Pvt. Ltd. 46

function login($username, $password){ _setValue(_textbox("user"), $username); _setValue(_password("password"), $password); _click(_submit("Login")); } function addBooks($numJava, $numRuby, $numPython){ _setValue(_textbox("q", _near(_cell("Core Java"))), $numJava); _setValue(_textbox("q", _near(_cell("Ruby for Rails"))), $numRuby); _setValue(_textbox("q", _near(_cell("Python Cookbook"))), $numPython); _click(_button("Add")); } function verifyTotal($total){ _assertEqual($total, _textbox("total").value); } function logout(){ _click(_button("Logout")); } function verifyNotLoggedIn(){ _assertExists(_textbox("user")); } function verifyErrorMessage($msg){ _assert(_isVisible(_div("errorMessage"))); _assertEqual($msg, _getText(_div("errorMessage"))); }

Executing the Excel Sheet


Executing the Excel sheet is no different from executing a Sahi script. Just copy the Excel sheet into sahi/userdata/scripts directory (or inside a sub-directory) and the xls file will be visible in the drop down in Controller Playback tab. Choose the file, Click "Set" and then "Play" to playback.

Play back reports/logs


On execution, Sahi generates logs showing success or failure. Logs are visible from the "Logs" link in Playback tab. Logs can also be accessed via http://sahi.example.com/_s_/dyn/pro/DBReports A sample log is shown below. Clicking any step expands to show the underlying Sahi steps. You can click on the log statements below.

Sahi Pro

Tyto Software Pvt. Ltd.

47

Starting script Expand All | Collapse All loadSahi Check shopping cart total [Documentation] login addBooks verifyTotal logout Test login error message [Documentation] login verifyNotLoggedIn verifyErrorMessage "Invalid username or password" Stopping script Checks Invalid login message "test" "bad password" "sample_lib.sah" Smoke test for add books "test" 3 1640 "secret" 2 1

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

Sahi Pro

Tyto Software Pvt. Ltd.

48

Syntax
Test Case Key word Argument 1 Argument Argument 2 3 Very first line of sheet Blank lines are ignored Loads a Sahi script with required function definitions Param2 New test case started. StepOne(Param1, Param2) is called. StepTwo(Param3) is called New test case started. String values are quoted

loadSahi

"custom_lib.sah"

Test Case One

Step One

Param1

Step Two Test Case Two Step One

Param3 25 "age"

Step Two

Param5 [Documentation] is useful for, well, documentation

Test [Documentation] Some Case description Three about the test case Step One 25 // Step Two Step Two Param5 Param6

"age"

New test case started. String values are quoted Commented step using //

Spaces will be removed from keywords and corresponding functions invoked. The rules for writing the Excel sheet are as follows The first line should be populated with Test Case | Key word | Argument 1 | Argument 2 | Argument 3 The names of the columns are not important, but they should not be left blank If the first column is populated, a new test case is started. The second column holds keywords. Keywords are mapped to functions in the included Sahi script. They can be user defined functions or Sahi APIs themselves

Sahi Pro

Tyto Software Pvt. Ltd.

49

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= _assertEqual _getText(_cell("msg")) $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 login

"In Global Setup" "test"

"secret"

[TearDown] _click _button("Logout") _log "In Global Teardown" Verify books total addBooks verifyTotal 3 1650 3 2000 2 1

Verify books again addBooks verifyTotal This will execute as: Sahi Pro

Tyto Software Pvt. Ltd.

50

_log login addBooks verifyTotal _click _log

"In Global Setup" "test" "secret" 3 2 1 1650 _button("Logout") "In Global Teardown"

_log login addBooks verifyTotal _click _log

"In Global Setup" "test" "secret" 3 2 2 2000 _button("Logout") "In Global Teardown"

Sahi Pro

Tyto Software Pvt. Ltd.

51

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 [CreateKeyword] Add AddBooksCheck Books Key Word Check [Arguments] $java

$ruby $python $total

[CreateKeyword] command creates a keyword called "Add Books Check" 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 verifyTotal 1650 1

Sahi Pro

Tyto Software Pvt. Ltd.

52

Data driven testing


Data [Keyword] Driven Example Add Books Check Starts a testcase "Data Drivern Example" AddBooksCheck function will be called for the data set below. This will be called BEFORE each row of data "test" "secret" This will be called AFTER each row of data _button("Logout") ruby 2 5 1 python total 1 0 9 1650 2100 3350 Ignored by Sahi. Makes test case more readable [Data] denotes start of data

[SetUp] login [TearDown] _click

[Documentation] java [Data] 3 4 0 This roughly translates to:

login "test" "secret" Add Books Check 3 2 1 _click _button("Logout") login "test" "secret" Add Books Check 4 5 0 _click _button("Logout") login "test" "secret" Add Books Check 0 1 9 _click _button("Logout")

1650

2100

3350

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

Sahi Pro

Tyto Software Pvt. Ltd.

53

Sahi Flex Support- sfl (Beta)


Introduction
Sahi Pro provides support for automation of flex applications. Before automating your flex application you will first need to compile your swf with the correct version of sfl.swc Eg. If your application is compiled with Flex 4.0, use sfl4.swc

Compile with sfl.swc using command line


You can compile your flex application with sfl using the following command (Change sfl version as needed) mxmlc yourapp.mxml -include-libraries+=sfl4.swc --output=yourapp.swf

Compile using Adobe Flash Builder (Add SWC files to Flex Builder projects)
In Flex Builder, select your Flex project in the Navigator. Select Project > Properties. The Properties dialog box appears. Select Flex Compiler in the tree to the left. The Flex Compiler properties panel appears. In the "Additional compiler arguments" field, enter the following command: -include-libraries "sfl4.swc"

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

Sahi Pro

Tyto Software Pvt. Ltd.

54

Recording a flex application

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

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

Sahi Pro

Tyto Software Pvt. Ltd.

55

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. 2. 3. 4. 5. 6. Run 1 (min) threads of noise.sah on PhantomJS (This will not be visible) Run subject.sah on firefox browser and store the time of steps. Wait for 5 seconds (interval) Run 2 (incrementby) more threads of noise.sah on PhantomJS Run subject.sah on firefox and store results Keep incrementing the noise threads at periodic intervals, run the subject, and store results, till it reaches max noise threads.

Once done, click on "Logs" link on the Dashboard to view results. To test your application, go to userdata/scripts/demo/load folder. 1. Open noise.sah and add your sequence of steps. These steps should be representative of a normal user interaction. Note that your steps should be in a while(true){} loop so that the threads don't die out. (Refer to existing noise.sah) 2. Open subject.sah and specify the sequence of steps whose reaction times you would like to measure at different loads. The parameters min, max, incrementby, interval etc. can be edited in dload.bat file. It is also possible to involve multiple machines in creating the load by modifying the "NODES" variable (Look in dload.bat)

Sahi Pro

Tyto Software Pvt. Ltd.

56

Appendix 1: Configure Sahi from the Dashboard


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

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

Sahi Pro

Tyto Software Pvt. Ltd.

57

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) _link("sahi_link") _link(/.*_link/) _link("Link to Sahi website") _link(/Link to .* website/) _link("/Link to .* website/") Using index in a page; assuming this is the 13th link on the page Using id as a string Using id as a regular expression Using visible text as a string Using visible text as a regular expression 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> Sahi Pro Tyto Software Pvt. Ltd. 58

There are two delete links in this table and there may be more. _link("delete") _link("delete[1]") _link("/del/[1]") points to the first delete link. This is the same as _link("delete[0]"). points to the second delete link; Note that indexing starts at 0. 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"))) _link("delete", _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. 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. points to the nearest link with text which matches regular expression /del/ near cell with text User Two. points to the 3rd nearest link with text delete near cell with text 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

_link(/del/, _near(_cell("User Two"))) _link("delete[2]", _near(_cell("User Two"))) _link("/del/[2]", _near(_cell("User Two")))

A similar DOM relation is _in _link(0, _in(_cell("del2"))) _link("delete", _in(_cell("del2")))

points to the 0th link in cell with id del2 points to the link with text delete within cell with id del2

Sahi Pro

Tyto Software Pvt. Ltd.

59

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 User One User Two delete delete

Status Active 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"))) _cell("Inactive", _under(_cell("Status"))) Finds first cell near User One and under Status Finds first Inactive cell under Status

Sahi Pro

Tyto Software Pvt. Ltd.

60

Accessors of HTML Elements: API HTML Identifier Example API HTML Identifier Notes Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example _link(identifier[, domRelation]) <a href="http://u/r/l" id="id">visible text</a> index, visible text, id _link("Sahi Website"); _image(identifier[, domRelation]) <img src="/path/to/images/add.gif" id="id" alt="alt" title="title"> index, title or alt, id, file name from src _image(add.gif) for an image with src /path/to/images/add.gif _image("title"); _label(identifier[, domRelation]) <label id="id">text</label> index, id, text _label("text"); _listItem(identifier[, domRelation]) <li id="id">text</li> index, id, text _listItem("text"); _div(identifier[, domRelation]) <div id="id">text</div> index, id, text _div("text"); _span(identifier[, domRelation]) <span id="id">text</span> Index,id,text _span("text");

Sahi Pro

Tyto Software Pvt. Ltd.

61

API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example

_spandiv(identifier[, domRelation]) <span id="id">text</span> or <div id="id">text</div> Index, id, text _spandiv("text"); _heading1(identifier[, domRelation]) <h1 id="id">text</h1> text, id _heading1("text"); _heading2(identifier[, domRelation]) <h2 id="id">text</h2> text, id _heading2("text"); _heading3(identifier[, domRelation]) <h3 id=id>text</h3> text, id _heading3("text"); _heading4(identifier[, domRelation]) <h4 id=id>text</h4> text, id _heading4("text"); _heading5(identifier[, domRelation]) <h5 id=id>text</h5> text, id _heading5("text");

Sahi Pro

Tyto Software Pvt. Ltd.

62

API HTML Identifier Example API HTML Notes Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example

_heading6(identifier[, domRelation]) <h6 id=id>text</h6> text, id _heading6("text"); _title() <title>text</title> Returns title of the page _title("text"); _area(identifier[, domRelation]) <area shape="rect" class="className" id="id" href="http://u/r/l" /> id, title|alt, href, shape, className, index _area("id"); _blockquote(identifier[, domRelation]) <blockquote class="className" id="id">sahiText</blockquote> sahiText, id, className, index _blockquote("sahiText"); _bold(identifier[, domRelation]) <b class="className" id="id">sahiText</b> sahiText, id, className, index _bold("sahiText"); _code(identifier[, domRelation]) <code class="className" id="id">sahiText </code> sahiText, id, className, index _code("sahiText");

Sahi Pro

Tyto Software Pvt. Ltd.

63

API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example

_emphasis(identifier[, domRelation]) <em class=className id=id>sahiText</em> sahiText, id, className, index _emphasis("sahiText"); _italic(identifier[, domRelation]) <i class="className" id="id">sahiText</i> sahiText, id, className, index _italic("sahiText"); _list(identifier[, domRelation]) <ul class="className" id="id">sahiText</ul> <ol class="className" id="id">sahiText</ol> id, className, index _list("sahiText"); _map(identifier[, domRelation]) <map class="className" id="id"></map> name, id, title, className, index _map("id"); _canvas(identifier[, domRelation]) <canvas class=classname id=id></canvas> sahiText, id, className, index _canvas("id"); _preformatted(identifier[, domRelation]) <pre class="className" id="id">sahiText</pre> sahiText, id, className, index _preformatted("sahiText");

Sahi Pro

Tyto Software Pvt. Ltd.

64

API HTML Identifier Example API HTML Identifier Example Since

_strong(identifier[, domRelation]) <strong class="className" id="id">sahiText</strong> sahiText, id, className, index _strong("sahiText"); _abbr(identifier[, domRelation]) <abbr class="className" id="id">sahiText</abbr> sahiText, id, className, index _abbr("sahiText"); 2011-07-19

Accessors of Table related elements API HTML Identifier Example API HTML _cell(identifier[, domRelation]) <td id="id">text</td> index, id, sahiText, className _cell("text"); _cell(tableElement, rowText, colText) <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> _cell(_table("tableId"), "header2", "value11"); This will point to cell with valuevalue11 _row(identifier[, domRelation]) <tr><td>te</td><td>xt</td></tr> id, className, sahiText, index _row(text) can be used to identify rows with text. Useful to look for cells in a row. _cell(text1,_in(_row(someClassName))) _row("text");

Example

API HTML Identifier Notes

Example

Sahi Pro

Tyto Software Pvt. Ltd.

65

API HTML Identifier Example API HTML Identifier Example

_table(identifier[, domRelation]) <table id="id">text</table> index, id, className _table("text"); _tableHeader(identifier[, domRelation]) <th id="id">text</th> sahiText, id, className _tableHeader("text");

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

Sahi Pro

Tyto Software Pvt. Ltd.

66

API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example

_submit(identifier[, domRelation]) <input type="submit" name="name" id="id" value="value"> <button type="submit" name="name" id="id">value</button> value, name, id, className, index (sahiText: valid for <button/>) _submit("value"); _textbox(identifier[, domRelation]) <input type="textbox" name="name" id="id" value="value"> name, id, index, className _textbox("name"); _reset(identifier[, domRelation]) <input type="reset" name="name" id="id" value="value"> <button type="reset" name="name" id="id"> value</button> value, name, id, index, className (sahiText: valid for <button/>) _reset("value"); _file(identifier[, domRelation]) <input type="file" name="name" id="id" value="value"> name, id, index, className _file("name"); _imageSubmitButton(identifier[, domRelation]) <input type="image" name="name" id="id" value="value" alt="alt" title="title" src="/images/file.gif"> title|alt, name, id, fileName, index, className _imageSubmitButton("title"); _imageSubmitButton("file.gif"); _select(identifier[, domRelation]) <select name="name" id="id"></select> name, id, index, className _select("id");

API HTML Identifier Example

Sahi Pro

Tyto Software Pvt. Ltd.

67

API HTML Identifier Notes Example

_option(identifier[, domRelation]) <option id="id" value="value">text</option> sahiText, value, id, index _option(selectElement, identifier) has been phased out since 2010-06-10. Please use _option(identifier, _in(selectElement)) instead. _option("text"); _option("text",_in(_select("selectedId"))); _textarea(identifier[, domRelation]) <textarea name="name" id="id">text</textarea> name, id, index, className _textarea("name"); _hidden(identifier[, domRelation]) <input type="hidden" name="name" id="id" value="value"> name, id, className, index _hidden("id");

API HTML Identifier Example API HTML Identifier Example

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

Sahi Pro

Tyto Software Pvt. Ltd.

68

API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example

_datetimelocalbox(identifier) <input type="datetime-local" name="name" id="id" value="value"/> name, id, index, className _datetimelocalbox("name"); _weekbox(identifier) <input type="week" name="name" id="id" value="value"/> name, id, index, className _weekbox("name"); _monthbox(identifier) <input type="month" name="name" id="id" value="value"/> name, id, index, className _monthbox("name"); _numberbox(identifier) <input type="number" name="name" id="id" value="value"/> name, id, index, className _numberbox("name"); _rangebox(identifier) <input type="range" name="name" id="id" value="value" min="min" max ="max"/> name, id, index, className _rangebox("name"); _telephonebox(identifier) <input type="tel" name="name" id="id" value="value"/> name, id, index, className _telephonebox("name");

Sahi Pro

Tyto Software Pvt. Ltd.

69

API HTML Identifier Example API HTML Identifier Example API HTML Identifier Example

_emailbox(identifier) <input type="email" name="name" id="id" value="value"/> name, id, index, className _emailbox("id"); _urlbox(identifier) <input type="url" name="name" id="id" value="value"/> index, name, id _urlbox("name"); _searchbox(identifier) <input type="search" name="name" id="id" value="value"/> Index, name, id _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 HTML Example _parentNode(element, tagname[, occurrence]) <div id="id"><a href="http://u/r/l">aElement</a></div> _parentNode("DIV", _link("aElement")); may return _div("id");

API HTML Example

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

Sahi Pro

Tyto Software Pvt. Ltd.

70

API HTML Example API HTML Example

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

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

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

Sahi Pro

Tyto Software Pvt. Ltd.

71

API HTML Identifier Notes Example API HTML Identifier Example API Identifier

_byText(identifier, tagName) <anytag>text</anytag> text This can be used for any tag with text. _byText("text"); _byClassName(identifier, tagName[, domRelation]) <anytag class="className">text</anytag> className _byClassName("text"); _byXPath(xpath[, domRelation]) xpath expression as string . This is a convenience method for people moving from Selenium or other tools to Sahi. 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/javascriptxpath/javascript-xpath.js and there is a README.txt which has these instructions This file is under its own MIT license and is not part of Sahis code base

Notes

Example

_byXPath("//table[3]//tr[1]/td[2]"); _byXPath("//tr[1]/td[2]", _in(_table(2))); _accessor(string) This API just evaluates the string and returns a dom object. This API is not too useful. _accessor("document.formName.elementName");

API Notes Example

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. Sahi Pro Tyto Software Pvt. Ltd. 72

API Notes Example

_lastAlert() Returns the message displayed in the last javascript alert popup. 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 Notes Example

_lastConfirm() Returns the message displayed in the last javascript confirm popup _lastConfirm returns the text of the last confirm which occured. 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 Notes Example

_lastPrompt() Returns the message displayed in the last javascript prompt popup. _lastPrompt returns the text of the last prompt which occured. 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 Notes Example

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

Sahi Pro

Tyto Software Pvt. Ltd.

73

Utility functions to access properties of elements API cssProperty Notes HTML Example API Notes Example _style(element, cssProperty) Any property declared via CSS i.e., height, background-color etc Returns the value of the style property for that element. <td style="background-color:red">cell text</td> _style(_cell("cell text"), "background-color"); returns rgb(255, 0, 0) _cookie(cookieName) Returns the value of the cookie with cookieName. _cookie("SESSID"); This may return 44159b7fdf524e97015f1982e65990d2 _position(element) Returns the array with the elements x, y coordinate in pixels. _position(_div("id")); If the div is present present at (100, 180), _position(el) will return [100, 180]. _getText(element) <div id=divId>This is some <b>bold</b> <a href=#>link</a></div> Returns the innerText or textContent of an element. _getText(_div("divId")); will return This is some bold link _getCellText(cellElement) <td id=dataId>cell text</td> Returns the innerText or textContent of an element. Same as _getText _getCellText(_cell("dataId")); _getSelectedText(selectElement) Returns the text of the selected option in a <select>tag Consider this HTML snippet: <select id="age"><option>21</option><option>32</option></select> If 32 is the selected option, then _getSelectedText(_select("age")); may return 32

API Notes Example

API HTML Notes Example API HTML Notes Example API Notes Example

Sahi Pro

Tyto Software Pvt. Ltd.

74

API Notes Example API Notes Example

_rteHTML(element) Returns the html inside a rich text editor. _rteHTML(_rte("rteId")); will return the rich text editors contents. _rteText(element) Returns the text inside a rich text editor. _rteText(_rte("rteId")); will return the rich text editors text content (without the html formatting). _isVisible(element) 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. _isVisible(_div("divId")); _exists(element) Returns true if the HTML element exists. Same as checking element != null. _exists(_link("Login")); _containsText(element, text) <div id="divId">some text displayed here</div> Returns true if the element contains the given text _containsText(_div("divId"), "some"); _containsHTML(element, html) <div id="divId">some <b>text</b></div> Returns true if the element contains the given html _containsHTML(_div("divId"), "<b>text</b>") ; returns true _contains(parentElement, childElement) <div id="id"><a href="http://u/r/l">aElement</a></div> Returns true if childElement is a child of parentElement _contains(_div("id"), _link("aElement")); returns true

API Notes

Example API Notes Example API HTML Notes Example API HTML Notes Example API HTML Notes Example

Sahi Pro

Tyto Software Pvt. Ltd.

75

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

API Notes

_near(element) Refer DOM Relations

Marker functions to show Positional relation API Notes Example _xy(element, x, y) Specifies the coordinates on element where the event is fired. _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 Notes _under(element) Refer Positional Relations

Sahi Pro

Tyto Software Pvt. Ltd.

76

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 Notes Syntax _click(element, combo) Clicks the element. _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 _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 clicksTest.sah

Example

Demo Script

API Notes Syntax

_rightClick(element, combo) Right clicks on an element. _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 _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 clicksTest.sah

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

77

API Notes Syntax

_doubleClick(element, combo) Double clicks on an element. _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 _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 clicksTest.sah _check(element) Checks the given checkbox or radio element. If already checked, this API does not do anything. _check( element ) element: element to be checked. Element should be a checkbox or radio element. _check("checkboxName"); _check("radioName"); checkbox.sah _uncheck(element) Unchecks the given checkbox. If already unchecked, this API does not do anything. _uncheck( element) element: element to be unchecked. Element should be a checkbox. _uncheck("checkboxName"); checkbox.sah

Example

Demo Script API Notes Syntax Example Demo Script API Notes Syntax Example Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

78

API Notes Syntax

_mouseOver(element, combo) Simulates a mouse over on the element. _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 _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 mouseEvents.sah _mouseDown(element, isRight, combo) Simulates a mouse down on the element. _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 _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 mouseEvents.sah

Example

Demo Script API Notes Syntax

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

79

API Notes Syntax

_mouseUp(element, isRight, combo) Simulates a mouse up on the element. _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 _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 mouseEvents.sah _simulateMouseEvent(element, type, isRight, isDouble, combo) Simulates any mouse event on an element. _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 _simulateMouseEvent(_button("Mouse Event"), "mousedown"); _simulateMouseEventXY(element, type, x, y, isRight, isDouble, combo) Simulates a mouse event on an element and triggers the event at (x, y) coordinates. The default coordinates are (0, 0) _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 _simulateMouseEventXY(_button("Mouse Event"), "mousedown", 10, 5);

Example

Demo Script API Notes Syntax

Example API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

80

API Notes Syntax

_dragDrop(draggable, droppable, offsetX, offsetY) Drags elementToDrag and drops on elementToDropOn _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 _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"));

Example

Demo Script

dragDrop.sah

Sahi Pro

Tyto Software Pvt. Ltd.

81

API Notes Syntax

_dragDropXY(draggable, x, y, isRelative) Drags elementToDrag and drops it on the given x, y coordinates. _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. If _image("item") is located at coordinates (50, 150) _dragDropXY(_image("item"), 100, 300); will drag the item and drop it at the coordinate (100, 300) The end result is that the elements coordinates will be at (100, 300) _dragDropXY(_image("item"), 100, 300, true); will drag the item and drop it at the coordinate (50+100, 150+300) The end result is that the elements coordinates will be at (150, 450)

Example

Demo Script

dragDropXY.sah

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

Sahi Pro

Tyto Software Pvt. Ltd.

82

API Notes Syntax Example Demo Script

_blur(element) Removes focus from element. _blur(element) element: Element to remove focus from _blur(_textbox("username")); focusTest.sah

Key Actions API Notes Syntax _keyPress(element, charInfo, combo) Simulates a keypress event for key with given charInfo on the element. _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 _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 keypress.sah _keyDown(element, charInfo, combo) Simulates a keydown event for key with given charInfo on the element. _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 _keyDown(_textbox("t2"), 'a'); _keyDown(_textbox("t2"), 97); _keyDown(_textbox("t2"), 'A', "SHIFT"); _keyDown(_textbox("t2"), [13,0]); //Press enter key google_search_dd.sah

Example

Demo Script API Notes Syntax

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

83

API Notes Syntax

_keyUp(element, charInfo, combo) Simulates a keyup event for key with given charInfo on the element. _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 _keyUp(_textbox("t2"), 'a'); _keyUp(_textbox("t2"), 97); _keyUp(_textbox("t2"), 'A', "SHIFT"); _keyUp(_textbox("t2"), [13,0]); //Press enter key google_search_dd.sah

Example

Demo Script

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

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

84

API Notes Syntax

_setSelected(element, option_identifier[, isMultiple]) Selects the option with option_identifier in select element. _setSelected ( element, option_identifier, isMultiple) element: HTML select element option_identifier: Options text, id or index; can also pass an array of options for multi-select isMultiple (Optional): true for multiselect _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 select.sah

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

85

API Notes Syntax

_setFile(element, filePath) Prepares the form to set file at filePath. _setFile(element, filePath [, actionURL]) element: HTML Form File Element whose value needs to be set filePath: Path of the file to be uploaded. actionURL (Optional): The form action URL to which the file is submitted. This is an optional parameter. Use it in cases where the forms action URL is changed on setting the file. By default, it uses the forms current action URL. _setFile(_file("id"), "C:\\abc\\efg.jpg"); _setFile(_file("id"), "C:\\abc\\efg.jpg", "formSubmit.jsp"); Note that _setFile works in a roundabout way. It is not handled at the browser level. It is handled at the proxy. So you will not see the file input box being populated with your desired filename. But when the form is submitted, the proxy will add the correct file to the request before it sends it to your web server. But if there are javascript checks before form submit to see if the filename is non-empty, then the script will not work as desired. If there are javascript validations on the file field, you can try this hack. Before submitting the file, change the fields type to text, and then set its value like this

Example

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

Example

Sahi Pro

Tyto Software Pvt. Ltd.

86

API Notes Syntax

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

Example

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 Notes Syntax _assertEqual(expected, actual, message) Asserts that expected and actual are equal, else logs the message. _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 _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. _assertNotEqual(expected, actual, message) Asserts that expected and actual are NOT equal, else logs the message. _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 _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.

Example

API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

87

API Notes Syntax

_assertNotNull(object, message) Asserts that the object is NOT null, else logs the message. _assertNotNull( object, message ) object: Any object message: Message to be written to logs if the expected and actual values are not equal _assertNotNull("abc"); This does nothing _assertNotNull(null, "Some Log Message"); This throws exception and writes Some Log Message to logs. _assertNull(object, message) Asserts that the object is null, else logs the message. _assertNull( object, message ) object: Any object message: Message to be written to logs if the expected and actual values are not equal _assertNull(null); This does nothing _assertNotNull("abc", "Some Log Message"); This throws exception and writes Some Log Message to logs. _assertTrue(condition, message) Asserts that the condition is true, else logs the message. _assertTrue( condition, message ) condition: Boolean expression message: Message to be written to logs if the expected and actual values are not equal _assertTrue(1==1); This does nothing _assertTrue(1==2, "Some Log Message"); This throws exception and writes Some Log Message to logs.

Example

API Notes Syntax

Example

API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

88

API Notes Syntax

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

Example

API Notes Syntax

Example

API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

89

API Notes Syntax

_assertExists(object, message) Asserts that the object is not null, else logs the message. _assertExists( object, message ) object: Any object message: Message to be written to logs if the expected and actual values are not equal _assertExists(_link("Back to form")); This does nothing _assertExists(null, "Some Log Message"); This throws exception and writes Some Log Message to logs. _assertNotExists(object, message) Asserts that the object does not exist (is null), else logs the message. _assertNotExists( object, message ) object: Any object message: Message to be written to logs if the expected and actual values are not equal _assertNotExists(null); This does nothing _assertNotExists(_link("Back to form"), "Some Log Message"); This throws exception and writes Some Log Message to logs. _assertContainsText(expectedText, object, message) Asserts that the object contains the expectedText, else logs the message. _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 _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"));

Example

API Notes Syntax

Example

API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

90

API Notes Syntax

_assertNotContainsText(expectedText, object, message) Asserts that the object does not contain the expectedText, else logs the message. _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 _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")); _assertEqualArrays(expected, actual, message) Asserts that expected and actual arrays are equal, else logs the message. _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 _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

Example

API Notes Syntax

Example

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

Example

Sahi Pro

Tyto Software Pvt. Ltd.

91

API Notes Syntax Example API Notes Syntax

_closeWindow() Closes the current window. This will work ONLY for popups. _closeWindow() _popup("popWin")._closeWindow(); _log(message, logLevel) Logs message into the playback logs. _log( message, logLevel ) message: Message to log type: where type can be success, failure, error, info, custom(1 - 5) _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 _wait(maxTime, condition) Waits for timeInMilliseconds ms or till the condition is satisfied on the browser, whichever is sooner. _wait( maxTime, condition ) maxTime: Time in milliseconds after which execution will resume condition: (Optional) Condition which when satisfied will resume execution _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 wait_for.sah

Example

API Notes Syntax

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

92

API Notes Syntax Example

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

Note: To fetch a value from a function on the browser and store it a variable in script, use _set <browser> function getRowCount(){ return _table("t1").rows.length; } </browser> var $count; _set ($count, getRowCount()); // Use $count _alert($count); Important: Sahi will evaluate the content in <browser> on the browser instead of the rhino engine. _call should be used sparingly and only if none of the inbuilt Sahi Browser Action APIs work.

Sahi Pro

Tyto Software Pvt. Ltd.

93

API Notes

_set( $variableName, value ) _set is used to fetch the value of a page dependent variable (something that is part of the browser page) and store it in a Sahi variable. You would need this to access Javascript attributes not already exposed by Sahis APIs. _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. 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);

Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

94

API Notes Syntax Example

_eval(string) Evals the string on the browser, instead of in the Rhino engine. _eval(string) string: String to evaluate _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 Notes Syntax

_callServer(cmd, qs) Calls server side code which cannnot be executed by javascript on the browser. _callServer(cmd, qs) cmd: String command of the form className_methodName qs: QueryString to be made available in the invoked method Below is an implementation of writing debug messages to the console. Create this class: package net.sf.sahi.ext; import net.sf.sahi.request.HttpRequest; public class Debug { public void toOut(HttpRequest request) { String msg = request.getParameter("msg"); System.out.println(msg); } } Add it to Sahis classpath: Look at Adding jars to Sahis classpath Call this from your script: _callServer("net.sf.sahi.ext.Debug_toOut", "msg=SomeMessage"); This will write SomeMessage on the console where sahi was started. Since Sahi V2, these actions can directly be performed by calling java classes from javascript through Rhino.

Example

Sahi Pro

Tyto Software Pvt. Ltd.

95

API Notes

_savedRandom( id, min, max ) 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. _savedRandom( id, min, max ) id: Any string min: Lower limit for the number generated max: Upper limit for the number generated _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. _resetSavedRandom(key) 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. _resetSavedRandom( key ) key: Id of the _savedRandom that needs to be reset _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 _random(max) Returns a random number between 0 and max _random( max ) max: Upper limit for the number generated _random(10); may generate any number between 0 and 10.

Syntax

Example

API Notes

Syntax Example

API Notes Syntax Example

Sahi Pro

Tyto Software Pvt. Ltd.

96

API Notes

_setGlobal(key, value) Stores the value in key for retrieval. The value persists across tests in a suite, if suite.global_variables is true in sahi.properties. _setGlobal( key, value ) key: identifier value: value associated with the key _setGlobal("userid1", _textbox("user").value); _getGlobal (key) Gets a previously stored variable whose scope will span a session. Globals are used for persisting variables across multiple web pages. _getGlobal ( key ) key: String identifying a global variable _setGlobal("name", "Ram"); _getGlobal("name"); // will return "Ram" _collect(apiType, id, inEl) Collects all elements of a particular type and stores them in an array. _collect(apiType, id[, inEl]) apiType: The type of API to collect id: A common identifier inEl (Optional): Parent element containing the elements to collect. 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])); collect.sah _count(apiType, id, inEl) Counts all elements of a particular type and stores them in a variable. _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. var $c = _count ("_link", "/group 1/"); $c may have a count of all links containing the text, group 1. _assertEqual(5, $c); collect.sah

Syntax

Example API Notes Syntax Example

API Notes Syntax

Example

Demo Script API Notes Syntax

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

97

Actions to mock out particular URLs Mocks are used to mock out responses to urls which match a particular pattern. For example: A web page has embedded advertisements in an iframe and we do not wish to test these advertisements everytime we test our web page. We can add a mock by specifying this to our script. _addMock("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds"); Whenever Sahi encounters a URL request which matches www[.]adserver[.]com It will delegate the response handling to sahi.ext.MyCustomMocks filterAds method. One can call any classs any method, as long as the method has one of these two signatures. public net.sf.sahi.response.HttpResponse methodName (net.sf.sahi.request.HttpRequest request); public void methodName(net.sf.sahi.request.HttpRequest request); If _addMock(pattern) is called without a second parameter, net.sf.sahi.command.MockResponder.simple(HttpRequest) is used to process the request. This response uses template at sahi/htdocs/spr/simpleMock.htm. One can modify this to show a generic mock response. By default this response just shows the mocked url. For images, one can use _mockImage, which is the same as _addMock except that it by default calls net.sf.sahi.command.MockResponder.mockImage(HttpRequest) which returns a simple image at sahi/htdocs/spr/mock.gif API Notes Syntax _addMock(pattern[, clazz_method]) Forces the proxy to process certain patterns of urls differently. If clazz_method is not specified, sends back a simple HTML blank page. _addMock(pattern[, clazz_method]) pattern: pattern to match clazz_method: method to send the response to _addMock("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds"); mock.sah

Example Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

98

API Notes Syntax

_mockImage(pattern[, clazz_method]) Similar to _addMock, but by default sends back an image. _mockImage(pattern[, clazz_method]) pattern: pattern to match clazz_method: method to send the response to _mockImage("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds"); _removeMock(pattern) Removes the mock behavior added via _addMock or _mockImage for that pattern. _removeMock(pattern) pattern: pattern to match _removeMock(".*sahi[.]co[.]in.*"); mock.sah

Example API Notes Syntax Example Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

99

Actions to set expectations for javascript confirms and prompts API Notes _expectConfirm(message, boolean) 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. _expectConfirm( message, boolean ) message: The visible text on the confirm dialog boolean: Expected boolean return value. _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 API Notes confirm.sah _expectPrompt(message, text) 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. _expectPrompt( message, text ) message: The visible text on the prompt dialog text: Input value _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 . prompt.sah

Syntax

Example

Syntax

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

100

API Notes Syntax Example Demo Script API Notes Syntax Example Demo Script API Notes Syntax Example Demo Script API Notes Syntax Example Demo Script

_clearPrintCalled() resets the value of _printCalled _clearPrintCalled() _clearPrintCalled(); print.sah _clearLastAlert() Clears the value returned by _lastAlert() _clearLastAlert() _clearLastAlert(); alert.sah _clearLastPrompt() Clears the value returned by _lastPrompt() _clearLastPrompt() _clearLastPrompt(); prompt.sah _clearLastConfirm() Clears the value returned by _lastConfirm() _clearLastConfirm() _clearLastConfirm(); confirm.sah

Actions used for debugging API Notes Syntax Example _highlight(element) Highlights an element with a red border. Use only for debugging. _highlight(element) element: HTML element to highlight _highlight(_div("Average")); This may look like this Average

Sahi Pro

Tyto Software Pvt. Ltd.

101

API Notes Syntax Example API Notes Syntax Example API Notes Syntax Example API Notes Syntax Example API Notes Syntax

_alert(message) Brings up a javascript alert with given message. Use only while debugging. _alert(message) message: message to show in alert _alert("Some message?"); _confirm(message) Brings up a javascript confirm with given message. Use only while debugging _confirm(message) message: message to show in confirm box _confirm("Do you wish to continue?"); _debug(message) Prints the message on to the console for debugging purposes. _debug(message) message: Message to print on the console _debug("Some message"); _debugToErr(message) Prints the message on to the error stream for debugging purposes. _debugToErr(message) message: Message to print _debugToErr("Some message"); _debugToFile(message, filePath) Prints the message into a file for debugging purposes. _debugToFile(message, filePath) message: Message to print filePath: Path of the file _debugToFile("Some message", "C:/errors.txt");

Example

Sahi Pro

Tyto Software Pvt. Ltd.

102

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

API Notes Syntax Example

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

Example

API Notes Syntax Example

Sahi Pro

Tyto Software Pvt. Ltd.

103

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

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

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 contenttype, 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 Notes Syntax Example Demo Script API Notes Syntax Example Demo Script

_saveDownloadedAs(filePath) Saves the file which was downloaded into sahi/temp/folder into the given filePath _saveDownloadedAs(filePath) filePath: Path where the file should be saved _saveDownloadedAs("c:/path/myfile.txt"); save_as.sah _clearLastDownloadedFileName() Clears the _lastDownloadedFileName (so that new files downloaded with the same fileName can be asserted) _clearLastDownloadedFileName() _clearLastDownloadedFileName(); save_as.sah

Sahi Pro

Tyto Software Pvt. Ltd.

105

Miscellaneous APIs
Functions available on browser and on proxy API Notes Example API Notes Example API Notes _scriptName() Returns the name of the current script _scriptName(); may return keypress.sah _scriptPath() Returns the path of the current script _scriptPath(); may return C:/keypress.sah _popup(identifier) 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. _popup( identifier ) identifier: windowName, windowTitle _popup("popWin")._click(_link("Click me")); _popup(/popWin.*/)._click(_link("Click me")); _popup("Window Title")._click(_link("Click me")); popup_title.sah _selectWindow(popupIdentifier) 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. _selectWindow( popupIdentifier ) popupIdentifier: windowName, windowTitle; if left blank, it chooses the base window _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; popup_title.sah

Syntax Example

Demo Script API Notes

Syntax

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

106

API Notes Example API Notes Example API Notes Example

_sessionInfo() Returns information of the current session. The object has attribures: isRecording isPlaying isPaused sessionId _sessionInfo(); _suiteInfo() Returns information of the current session. _suiteInfo(); _userDataDir() Returns absolute path to userdata directory. _userDataDir(); may return C:/sahi_pro/userdata/ _userDataPath(relativePath) Returns absolute path to userdata directory, given a relative path. _userDataPath("scripts"); may return C:/sahi_pro/userdata/scripts/ _lastDownloadedFileName() Returns the name of the last downloaded file name. _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.

API Notes Example

API Notes Example

Sahi Pro

Tyto Software Pvt. Ltd.

107

API Notes

_setStrictVisibilityCheck(boolean) 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. strict_visible.sah

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

108

Functions available on proxy only API Notes Syntax _logException(exception) Exceptions are handled via regular javascript try catch blocks since Sahi V2. 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 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 Notes Example API Notes Example _stopOnError() Makes the script stop if an error occurs. This is the default behavior. _stopOnError(); _continueOnError() Makes script continue inspite of errors. Can be turned off with _stopOnError() _continueOnError();

Example

Sahi Pro

Tyto Software Pvt. Ltd.

109

API Notes Syntax

_logExceptionAsFailure(exception) Exceptions are handled via regular javascript try catch blocks since Sahi V2 try{ // sahi statements }catch(exception){ // Corrective action _logExceptionAsFailure( exception ); // Can print exact source of error in log // Can throw the same or another exception } 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. }

Example

Demo Script

log_exception_as_failure.sah

Sahi Pro

Tyto Software Pvt. Ltd.

110

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 Notes

_setRecovery(fn) 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(). _setRecovery( fn ) fn: recovery function _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.

Syntax Example

Sahi Pro

Tyto Software Pvt. Ltd.

111

API Notes Syntax Example

_removeRecovery(fn) Removes any recovery function which was set via _setRecovery(fn). _removeRecovery(fn) fn: recovery function _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 Sahis external classpath. More info: Adding jars to Sahis classpath select( sql ): The result set that is returned by the select statement is a list of rows. Rows are accessible by index. For example: ID 1 2 3 NAME Kamalesh Arun Raja AGE 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");

Sahi Pro

Tyto Software Pvt. Ltd.

112

$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 Notes Syntax _getDB(driver, jdbcurl, username, password) Returns a DB object which can be used to query the database. _getDB is used to connect to a database. _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 For table User ID NAME 1 Kamalesh 2 Arun 3 Raja AGE 28 30 35

Example

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. Sahi Pro Tyto Software Pvt. Ltd. 113

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 20 Male Ramu 30 Male Sheela 25 Female // Get the DB instance var db = _getDB("sun.jdbc.odbc.JdbcOdbcDriver", "jdbc:odbc:Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=D:\\myfolder\\sample.xls;readOnly=false", "", ""); // Run a select $rs = db.select("select * from [Sheet1$]"); // Assert the first row has Raju in the Name column _assertEqual("Raju", $rs[0]["Name"]); // Assert the first row has 20 in the Age column. // All values will be strings, so we need to parseInt the age. _assertEqual(20, parseInt($rs[0]["Age"])); // Run an update. db.update("update [Sheet1$] set Age=21 where Name='Raju'"); // Do a select again to verify $rs = db.select("select * from [Sheet1$]"); _assertEqual(21, parseInt($rs[0]["Age"])); Note the readOnly=false in the connection string on the first line. This is required if you wish to update the Excel sheet. If you do not add readOnly=false, you will get an error like this: java.sql.SQLException: [Microsoft][ODBC Excel Driver] Operation must use an updateable query.

Sahi Pro

Tyto Software Pvt. Ltd.

114

Working with files API Notes Syntax _readFile(filePath) Returns the contents of the file as a single String. This is the simplest way of reading a files contents. _readFile( filePath ) filePath: Path of file to read. Paths are relative to the scripts location. Specify absolute path if the file should be read from any other path. var $contents = _readFile("C:/contents.txt"); Here, $contents is a string that contains text from contents.txt readfile.sah _writeFile(text, filePath[, overwrite]) Writes the text into file at filePath. _writeFile( text, filePath[, overwrite] ) text: text to write filePath: Path of file to write to. Paths are relative to the scripts location. Specify absolute path if the file should be created in any other path. overwrite: true if contents of file need to be overwritten. Default: false _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 _writeToFile(text, filePath[, overwrite]) Writes the text into file at filePath. _writeToFile( text, filePath[, overwrite] ) text: text to write filePath: Path of file to write to. Paths are relative to the scripts location. Specify absolute path if the file should be created in any other path. overwrite: true if contents of file need to be overwritten. Default: false _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

Example Demo Script API Notes Syntax

Example

API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

115

API Notes Syntax

_readCSVFile(filePath, wordSeparator) 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. _readCSVFile(filePath, wordSeparator) filePath: Path of the CSV file to read. Paths are relative to the scripts location. Specify absolute path if the file should be read from any other path. wordSeparator: Separator between words. Default: , (comma) 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. csv.sah _writeCSVFile(array2d, filePath, overwrite, wordSeparator) Writes a 2 dimensional array into a file in CSV format, using the given wordSeparator (default is comma) _writeCSVFile( array2d, filePath[, overwrite, wordSeparator] ) array2d: 2 dimensional array filePath: Path of the file to write to. Paths are relative to the scripts location. Specify absolute path if the file should be created in any other path. overwrite: if true, overwrites the file. Default: false wordSeparator: Separator between words var $ar = new Array(); $ar[$ar.length] = [ "hi", "there", "one", "a\"b"]; _writeCSVFile($ar, "sahicsv.txt", true); csv.sah _deleteFile(filePath) Deletes the file at filePath. _deleteFile(filePath) filePath: Path of the file to delete. Paths are relative to the scripts location. Specify absolute path if the file should be deleted from any other path. _deleteFile("sahicsv.txt");

Example

Demo Script API Notes Syntac

Example

Demo Script API Notes Syntax

Example

Sahi Pro

Tyto Software Pvt. Ltd.

116

API Notes Syntax

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

Example

Data driven testing Sahi has some nice inbuilt features for data-driven testing. The core concept is that data is present as a grid of rows and columns, and tests need to run with each row of the grid as input. Suppose we have a 2-dimensional array of data, on which we perform an add operation: function doAdd($first, $second, $total){ _setValue(_textbox("first"), $first); _setValue(_textbox("second"), $second); _click(_button("Add")); _assertEqual($total, _textbox("total").value); } var $data = [[2, 3, 5], [1, 2, 4], [4, 3, 7]] A simple way to do this is to iterate over the array and invoke the doAdd function with values from each row. for (var $i=0; $i<$data.length; $i++){ var $row = $data[$i]; doAdd($row[0], $row[1], $row[2]); } But, this loop will fail in the second row, since 1+2=3 and not 4, as given in the second row. In case of failure we need to continue to the next row and not stop there. To do this, we use a try catch block. for (var $i=0; $i<$data.length; $i++){ var $row = $data[$i]; try{ doAdd($row[0], $row[1], $row[2]); } catch (e) { // The try catch block helps in continuing with the next // step of data inspite of failures. // _logException so that the logs will indicate the failing line. _logException(e); }} Sahi Pro Tyto Software Pvt. Ltd. 117

All this looping and try catch have been neatly wrapped into a utility function _dataDrive. API Notes Syntax _dataDrive(fn, data2DArray) Loops over data2DArray, and invokes function fn with each row of data. The invocation is within a try catch block with exception logging. _dataDrive(fn, data2DArray) fn: function to call data2DArray: 2 dimensional array to iterate over 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()

Example

Sahi Pro

Tyto Software Pvt. Ltd.

118

APIs for browser detection API Notes API Notes API Notes API Notes API Notes _isIE(), _isIE9() Returns true if browser is Internet Explorer _isFF(), _isFF2(), _isFF3(), _isFF4(), isFF5() Returns true if browser is Mozilla Firefox _isChrome() Returns true if browser is Google Chrome _isSafari() Returns true if browser is Safari _isOpera() 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. API Notes Example _takeSnapShot() _takeSnapShots( toggle ) _takeSnapShot() Used to take a snapshot of a single step _click(_link("Click me")); _takeSnapShot(); This will capture the state of the screen when the link Click me is clicked. createSnapShot.sah

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

119

API Notes Syntax

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

Example

Demo Script

Sahi Pro

Tyto Software Pvt. Ltd.

120

Appendix 3: Integrate with Jenkins


Before integration, you will first need an Ant target to run the suite file. Save this code snippet in Sahis root folder as jenkins-sample.xml.
<project name="demo" default="ff"> <property name="userdata.dir" value="${basedir}/userdata"/> <property environment="env" /> <property name="urlbase" value="sahi.co.in"/> <taskdef name="sahi" classname="net.sf.sahi.ant.RunSahiTask" classpath="lib/ant-sahi.jar"/> <target name="ff" description="start the server and run sahi tests"> <parallel> <sequential> <waitfor maxwait="3" maxwaitunit="minute" checkevery="100"> <http url="http://localhost:9999/logs/"/> </waitfor> <antcall target="runfftests"/> <antcall target="stopsahi"/> </sequential> <antcall target="start"/> </parallel> </target> <target name="runfftests"> <sahi suite="../userdata/scripts/demo/demo.suite " browserType="firefox" baseurl="http://${urlbase}/demo/" sahihost="localhost" sahiport="9999" failureproperty="sahi.failed" haltonfailure="false" userDefinedId="sahi.co.in_firefox_english" threads="6"> <customfield key="language" value="english"/> <report type="junit" logdir="${userdata.dir}/temp/junit/tests"/> </sahi> <antcall target="report-gen"/> <antcall target="failsahi"/> </target> <target name="report-gen"> <delete dir="${userdata.dir}/temp/junit/reports/sahi-html"> </delete> <mkdir dir="${userdata.dir}/temp/junit/reports" /> <junitreport todir="${userdata.dir}/temp/junit/reports"> <fileset dir="${userdata.dir}/temp/junit/tests/junit"> <include name="TEST-*.xml" /> </fileset> <report format="frames" todir="${userdata.dir}/temp/junit/reports/sahi-html" /> </junitreport> </target>

Sahi Pro

Tyto Software Pvt. Ltd.

121

<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". Tyto Software Pvt. Ltd. 122

Sahi Pro

After the tests have run, you will be able to see "Latest Test Result" on the Project home page. Click on it to view your results. You should have all the reports created at this point.

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

You CAN customize a test to run from Jenkins without moving Sahi into the workspace. Familiarity of Jenkins and Ant is necessary to achieve this.

Sahi Pro

Tyto Software Pvt. Ltd.

123

Appendix 3: Configuring Sahi with Xvfb


It is sometimes good to run tests headless (without a user interface). It is faster and allows the user to perform other tasks on the computer, while the tests are being run in background. On linux systems, Firefox can be configured to use Xvfb to run Sahi tests in headless mode.

What is xvfb?
From wikipedia (http://en.wikipedia.org/wiki/Xvfb): Xvfb or X virtual framebuffer is an X11 server that performs all graphical operations in memory, not showing any screen output. From the point of view of the client, it acts exactly like any other server, serving requests and sending events and errors as appropriate. However, no output is shown. This virtual server does not require the computer it is running on to even have a screen or any input device. Only a network layer is necessary.

Installing Xvfb:
For ubuntu, run apt-get install Xvfb For Fedora, run yum install Xvfb For other linux, Download xvfb.tgz from http://ftp.xfree86.org/pub/XFree86/4.6.0/binaries/FreeBSD-4.x/ Let us consider that the downloaded file is at ~/Downloads. cd / tar xvf ~/Downloads/xvfb.tgz cd /usr sudo mkdir X11R6 sudo cp ~/Downloads/xvfb/*.* /usr/X11R6/ chmod +x bin/Xvfb cd bin Create a new file Xvfb and add the script below,

Sahi Pro

Tyto Software Pvt. Ltd.

124

#!/bin/sh mode=$1 case "$mode" in 'start') if [ -f /usr/X11R6/bin/Xvfb ]; then echo "***Starting up the Virtual Frame Buffer on Screen 1***" /usr/X11R6/bin/Xvfb :1 -screen 0 1152x900x8 & fi ;; *) echo " Usage: " echo " $0 start (start XVFB)" echo " $0 stop (stop XVFB - not supported)" exit 1 ;; esac exit 0

chmod +x Xvfb

Setting up Xvfb on display 1:


export DISPLAY=:1.0 firefox startx -- `which Xvfb` :1 -screen 0 1024x768x24

Running test in Xvfb headless browser through Sahi:

Configure sahi/userdata/config/browser_types.xml to have browser entries as below,


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

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

Sahi Pro

Tyto Software Pvt. Ltd.

125

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

var $x = new XML(xmlStr); _assertEqual("Ant", $x.person[0].name.toString()); _assertEqual("Grey", $x.person[1].eyes.toString()); for each (var $p in $x.person){ var $measure = $p.height.@measure.toString(); _assert($measure == "metric"); _assert($p.height > 170); }

Sahi Pro

Tyto Software Pvt. Ltd.

126

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 displayName icon path options processName capacity

key by which this browserType will be referred Text visible on the Sahi Dashboard png icon. These are bundled inside Sahi path to browser executable. If you run this from a command line, it should invoke the browser options needed by browser. Generally this sets the proxy, and isolates browser sessions so that cookies are not shared. the processName for looking up PID of process. Sahi will do a tasklist or ps with this name to identify the process to kill maximum number of browsers simultaneously executable without overwhelming the system. This depends on your system and you can configure this based on your judgement true/false Specifies if Windows system proxy settings should be changed to use Proxy. Needed by Internet Explorer and Safari on Windows 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

useSystemProxy force

If your browser is installed in a non standard directory, edit sahi/userdata/browser_types.xml and set the correct path. Alternately, you can click on Configure link on the Sahi Dashboard and edit browser_types.xml. Sahi needs to be restarted for the settings to take effect. Sahi Pro Tyto Software Pvt. Ltd. 127

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

Sahi Pro

Tyto Software Pvt. Ltd.

128

Click Yes to import the certificate. 3. If Step 2 fails, Sahi will then try a direct import. Follow these steps.

Sahi Pro

Tyto Software Pvt. Ltd.

129

1 2

5 4

Sahi Pro

Tyto Software Pvt. Ltd.

130

This should import the certificate successfully. Sahi Pro Tyto Software Pvt. Ltd. 131

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)

Sahi Pro

Tyto Software Pvt. Ltd.

132

Controller does not identify elements on one website. It works for other websites.
Do a view source on the page and search for document.domain. You may see something like: document.domain = "maindomain.com" This is done by the application developer, so that two frames/iframes from domains like a.maindomain.com and b.maindomain.com can communicate with each other via javascript. To make Sahi work correctly with this, open sahi/userdata/config/domainfix.txt and add *.maindomain.com maindomain.com Save, restart Sahi, and now the Controller should work correctly.

Playback starts but keeps waiting on some page


Sahi waits on AJAX requests to make sure they are complete, before proceeding with playback. Some sites keep some AJAX requests open so that they can continuously poll for data. This causes Sahi to indefinitely wait for those requests to complete. 1. To fix this: Open sahi/userdata/config/userdata.properties 2. Add (or edit) xhr.wait_ready_states=2,3 3. Save the file, and restart Sahi This should fix the issue.

Connecting through VPNs for IE


(This also needs to be done for data cards like Tata Photon, Reliance etc.) Sahi sets the IE LAN proxy settings to localhost 9999 automatically. When going through a VPN, you do not use the LAN, so Sahis settings would not work. To fix this you need to 1. Manually configure IE to use Sahi for the VPN connection 2. Optionally, tell Sahi to not change the LAN settings (optional: do this only if you will never use LAN) To accomplish this, please follow the instructions below: 1. On IE, go to Tools -> Internet Options -> Connections -> Dial-up and Virtual Private Network Settings. There choose your VPN, and click on Settings button near it. Set localhost 9999 for HTTP and Secure. Now Sahi should work correctly over your VPN. 2. (Optional, do this only if you will never use LAN) Open browser_types.xml from the Configure link on dashboard, and remove <useSystemProxy>true</useSystemProxy> line from Internet Explorer settings (You can remove it where ever it is present.) Save, restart Sahi, and now Sahi will not try to change proxy settings of your system. Sahi Pro Tyto Software Pvt. Ltd. 133

Appendix 6: Sahi headless execution with PhantomJS


PhantomJS is a headless browser based on WebKit. (A headless browser runs without a user interface) To run Sahi headless on PhantomJS:

Quick start guide for using PhantomJS with Sahi Pro for load testing:
Download phantomjs-1.x.x-win32-dynamic.zip from http://code.google.com/p/phantomjs/downloads/list Unzip phantomjs-1.x.x-win32-dynamic.zip inside sahi/ext/phantomjs/ folder such that you have sahi/ext/phantomjs/phantomjs.exe

Normal Installation:
1. Download phantomjs-1.x.x-win32-dynamic.zip from http://code.google.com/p/phantomjs/downloads/list 2. Unzip it to, say C:\phantomjs-1.x.x-win32 such that phantomjs.exe is available at C:\phantomjs-1.x.x-win32\phantomjs.exe 3. Create a file sahi.js in C:\phantomjs-1.x.x-win32 with the content below: For version 1.1.0, use:
if (phantom.state.length === 0) { if (phantom.args.length === 0) { console.log('Usage: sahi.js <Sahi Playback Start URL>'); phantom.exit(); } else { var address = unescape(phantom.args[0]); phantom.state = "sahi script running"; console.log('Loading ' + address); phantom.open(address); } } else { if (phantom.loadStatus === 'success') { console.log('Page title is ' + document.title); } else { console.log('FAIL to load the address'); } }

For version 1.2.0 onwards, use:

Sahi Pro

Tyto Software Pvt. Ltd.

134

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.

Sahi Pro

Tyto Software Pvt. Ltd.

135