| ## Sahi - Web Automation and Test Tool Documentation in this directory is not current. Please visit http://sahi.co.in/ for the latest documentation. ## APIs The best way to learn how these APIs work is by recording actions using the Sahi controller and looking at the recorded code. Accessor Functions : Form elements Accessor Functions : Link Accessor Functions : Tables Accessor Functions : Generic Action Scheduler Functions Assertion Scheduler Functions Text Access Functions Text Verification boolean Functions File Inclusion Utility Functions Database Functions File Read Functions Handling popup windows (Top) #### Accessor Functions : Form elements _textbox(idStr) _password(idStr) _checkbox(idStr) _textarea(idStr) _select(idStr) _option(selectElement, text) _radio(idStr) _image(idStr) _button(idStr) _submit(idStr) _lastConfirm() _lastPrompt() _file(idStr) (Top) #### Accessor Functions : Link _link(idStr) (Top) #### Accessor Functions : Tables _table(idStr) _cell(tableEl, rowNo, colNo) _cell(tableEl, someTextWhichIdentifiesRow, someTextWhichIdentifiesColumn) _cell(cellIdStr) _row(tableEl, rowNo) _row(tableEl, someTextWhichIdentifiesRow) (Top) #### Accessor Functions : Generic _accessor(idStr) (Top) #### Scheduler Functions Scheduler Functions behave differently from normal functions. They schedule the execution of the action for later execution in a different thread. They essentailly have the effect of converting the whole statement into a string and adding it to a global array. Each statement from the array is then executed one at a time, with a delay, when its turn comes. Note: All these functions can also be made to execute instantly (and not delayed) by using __ (double underscores) instead of _ (single underscore) (Top) #### Action Scheduler Functions These are Scheduler Functions _click(jsElement) _clickImage(jsElement) _dragDrop(draggableElement, dropDestinationElement); _setValue(jsElement, val) _setSelected(jsElement, val) _check(jsElement, val) _simulateEvent(jsElement, ev) _wait(millis) _alert(str) _setGlobal(name, value) _call(fn()) _log(message, type) where type can be "success", "failure", "error", "info" _highlight(jsElement) _navigateTo("URLString") _callServer("class_method", "querystring") _addMock("pattern") _addMock("pattern", "class_method") _removeMock("pattern") _expectConfirm() _expectPrompt() _setFile(_file("id"), filePath) (Top) #### Assertion Scheduler Functions These are Scheduler Functions _assertNotNull(jsElement, msg) _assertNull(jsElement, msg) _assertEqual(expected, actual, msg) _assertNotEqual(expected, actual, msg) _assertTrue(condition, msg) _assertNotTrue(condition, msg) (Top) #### Text Access Functions _getSelectedText(selectElement) _getCellText(tableCellElement) (Top) #### Text Verification boolean Functions _containsText(element, textToSearch) _containsHTML(element, htmlToSearch) (Top) #### File Inclusion _include(filePath) _include(filePath) One sah file may include other sah files, thus allowing logical separation of code. Syntax: _include(file2.sah) Example: File create_customer.sah
        _include("create_customer_Functions.sah");
        createCustomer("Narayan", 1001, 27);
File create_customer_Functions.sah
        function createCustomer($name, $id, $age){
        _setValue(_textbox("name"), $name);
        _setValue(_textbox("id"), $id);
        _setValue(_textbox("age"), $age);
        }
(Top) #### Utility Functions _savedRandom(id, minNo, maxNo) _resetSavedRandom(id) _setGlobal(name, value) _getGlobal(name) _debug(msg) _debugToErr(msg) _debugToFile(msg, filePath) _savedRandom(id, min, max) If a script was recorded for say, creating a user, and if the user name is mandated to be unique in the application, we need to add random numbers to the user name so that it remains unique. One can obtain a random number by using _savedRandom(id, min, max). During the first call to it, it creates a random number between min and max, associates with the id and returns the number. On subsequent accesses with that id, it returns the same random number which it had created in the first access. Example:
        var $x = _savedRandom("login", 100, 200); //sets $x to say 145 (a random number between 100, 200).
        //Defaults for min and max, if omitted, are 0 and 10000
        $y = _savedRandom("login", 100, 200); //will set $y to 145 again.
        $y = _savedRandom("login"); //will also set $y to 145.
The min and max are needed only during the first call. _resetSavedRandom(id) _resetSavedRandom(id) resets value of _savedRandom(id) to null; _setGlobal(name, value) and _getGloblal(name) Since a script may span across multiple web pages, variables from one page may need to be stored for later use. For example, an id which is generated on customer creation may need to stored for later look up of the customer, on a different page. This can be accomplished by _setGlobal(name, value) and _getGloblal(name). Example:
        _setGlobal("customerId", _getCellText(_cell("custId"))); // sets the text in table cell with id "custId" into a
        global variable keyed by "customerId"
Then on a later page, one can retrieve the customerId through
        _setValue(_textbox("lookup"), _getGlobal("customerId")); // the second parameter retrieves the text stored.
These variables are stored on the server in a hashmap associated with the session. Note: that all values will be stored as strings only. Note: _setGlobal is a Scheduler Function. _debug(msg) Writes the message to the standard output stream. The messages will be visible on the window where the proxy is running unless redirected. _debugToErr(msg) Writes the message to the standard error stream. The messages will be visible on the window where the proxy is running unless redirected. _debugToFile(msg, filePath) Writes the message to the file specified. (Top) #### Handling popup windows _popup(windowName) _popup(windowName) In order to execute sahi commands in a popup window, for example click a link, use
        _popup("popupWinName")._click(_link("Click Me"));
where popupWinName was defined like this:
        window.open("http://popup.url", "popupWinName");
or
        <a href="http://popup.url" target="popupWinName">
Note that there may be problems in recording this. (Top) #### _callServer("class_method", "querystring") _callServer allows Sahi to execute any server side code. Example:
        Create this Counter class. You will need sahi.jar in the compilation path.

        package sahi.ext;

        import net.sf.sahi.request.HttpRequest;
        import net.sf.sahi.response.HttpResponse;
        import net.sf.sahi.response.SimpleHttpResponse;

        public class Counter {
        static int counter = 0;

        public void incrementCounter(HttpRequest request) {
        counter++;
        }

        public HttpResponse getCounter(HttpRequest request) {
        return new SimpleHttpResponse(""+counter);
        }

        }

        Add this class to Sahi's class path.
        For example, if you are using sahi.bat, you could add it to the path like this:
        java -classpath ..\lib\sahi.jar;C:\sahiext\classes; net.sf.sahi.Proxy

        Restart Sahi

        Now we can call the methods of Counter class from any Sahi script in this way:
        var $currentCount = parseInt(_callServer("sahi.ext.Counter_getCounter"));
        _callServer("sahi.ext.Counter_incrementCounter");
        _assertEqual($currentCount + 1, _callServer("sahi.ext.Counter_getCounter"));
#### Mocks 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. So we can add a mock by specifying
    _addMock("www[.]adserver[.]com", "sahi.ext.MyCustomMock_filterAds");
to our script. Whenever Sahi encounters a URL request which matches www[.]adserver[.]com It will delegate the response handling to sahi.ext.MyCustomMock's filterAds method. One can call any class's any method, as long as the method has one of these two signatures.
        public net.sf.sahi.response.HttpResponse methodName(net.sf.sahi.request.HttpRequest request);

        public void methodName(net.sf.sahi.request.HttpRequest request);
If _addMock("pattern") is called without a second parameter, net.sf.sahi.command.MockResponder.simple(HttpRequest) is used to process the request. The response uses the template at htdocs/spr/simpleMock.htm. One can modify this to show a generic mock response. This script may explain mocks better:
        _navigateTo("http://localhost:10000/demo/index.htm");
        _assertNotNull(_link("Link Test"));
        _addMock(".*localhost.*");
        _navigateTo("http://localhost:10000/demo/index.htm");
        _assertNull(_link("Link Test"));
        _containsText(document.body, "http://localhost:10000/demo/index.htm");
        _removeMock(".*localhost.*");
        _navigateTo("http://localhost:10000/demo/index.htm");
        _assertNotNull(_link("Link Test"));
(Top) #### Confirm Javascript calls to confirm(msg) are mocked out by Sahi so that it does not stop the 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(label, 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();
#### Example:

        <script type="text/javascript">
            function showConfirm(){
                var t1 = document.f1.t1;
                if (confirm("Some question?")){
                    t1.value = "oked";
                }else{
                    t1.value = "canceled";
                }
            }
        </script>
        <form name="f1">
            <input type="button" name="b1" value="Click For Confirm" onclick="showConfirm()">
            <input type="text" name="t1">
        </form>

        _click(_button("Click For Confirm"));
        _assertNotNull(_textbox("t1"));
        _assertEqual("oked", _textbox("t1").value);
        _assertEqual(_lastConfirm(), "Some question?");

        _expectConfirm("Some question?", false);
        _click(_button("Click For Confirm"));
        _assertNotNull(_textbox("t1"));
        _assertEqual("canceled", _textbox("t1").value);
        _assertEqual(_lastConfirm(), "Some question?"); //Kind of redundant here.
(Top) #### Prompt 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. It is possible to make the prompt return the value one wants, by specifying
        _expectPrompt(label, value);
before the statement which triggers the prompt dialog. If there was no expectation set, Sahi will return "". It is also possible to get the text of the last occurred prompt dialog using
        _lastPrompt();
#### Example:

        <script type="text/javascript">
        function showPrompt(){
            var t2 = document.f2.t2;
            t2.value = prompt("Some prompt?");
        }
        </script>
        <form name="f2">
            <input type="button" name="b1" value="Click For Prompt" onclick="showPrompt()"><br><br>
            <input type="text" name="t2">
        </form>

        _expectPrompt("Some prompt?", "abc")
        _click(_button("Click For Prompt"));
        _assertNotNull(_textbox("t2"));
        _assertEqual("abc", _textbox("t2").value);
        _assertEqual(_lastPrompt(), "Some prompt?");
(Top) #### _setFile(_file("id"), filePath) Form elements of type "file" cannot be populated using javascript on the browser. So Sahi has a workaround for handling file uploads. Sahi intercepts the request in the proxy, reads the file off the file system and inserts it into the multipart request.
        _setFile(_file("id"), "C:\\abc\\efg.jpg");
The file has to be present on that path on the machine running the proxy. (Top) #### _getDB("driver", "jdbcurl", "username", "password") _getDB returns a sahiDB object. sahiDB has two methods. select(sql); // select statements update(sql); // update/delete/insert statements select returns a sequential array of associative arrays. Eg. For table "User"
ID | NAME | AGE
1 | Kamlesh | 28
2 | Arun | 30
3 | Raja | 35
    var db = _getDB("oracle.jdbc.driver.OracleDriver", "jdbc:oracle:thin:@dbserver:1521:sid", "username", "password")
    var $rs = db.select("select * from User");

    _assertEqual("1", $rs[0]["ID"]);
    _assertEqual("Kamlesh", $rs[0]["NAME"]);
    _assertEqual("28", $rs[0]["AGE"]);

    _assertEqual("2", $rs[1]["ID"]);
    _assertEqual("Arun", $rs[1]["NAME"]);
    _assertEqual("30", $rs[1]["AGE"]);

    _assertEqual("3", $rs[2]["ID"]);
    _assertEqual("Raja", $rs[2]["NAME"]);
    _assertEqual("36", $rs[2]["AGE"]);
The driver has to be present in the classpath of Sahi. For example, if you are using sahi.bat, you could add it to the path like this: java -classpath ..\lib\sahi.jar;C:\sahiext\driver.jar; net.sf.sahi.Proxy (Top) #### _readFile(fullFilePath) _readFile(fullFilePath) returns the contents of a text file as a string.
        _readFile("C:\\abc\\data.txt");
The file has to be present on that path on the machine running the proxy. One could then use the JS String's split method to get an array of lines. eg.
            var $content = _readFile("C:\\abc\\data.txt");
            var $lines = $content.split("\n");
(Top)

Please send your feedback to V Narayan Raman.