Enable javascript in your browser for better experience. Need to know to enable it? Go here.
Blogs Banner

An introduction to Sahi: Part 2

Part 2 of our overview of Sahi. For ways to get started on Sahi, check out Part 1 here.


Our project is an ExtJS based website. Most element ids are generated dynamically which means the id is not reliable as locator. Sahi provides us with the ability to use position dependency to locate elements.

In our system, the source image of all drop down lists is “s.gif”. And there are 20 dropdown list images with the same source “s.gif”. So if we use XPath img[@src=”s.gif”], it will give us 20 results. Then we have to use the index which may change when we add a new dropdown list image. By default Sahi’s accessor spy will also identify elements by indexes like “s.gif”,”s.gif[1]”. However, Sahi provides an alternative to express the image by using _near API.

The same image can be identified as


which means the image named “s.gif” where it is near _label("Search:"). In this way, we can always find the image most close to Search, which is our target.


With _near(), we can find the nearest element, but sometimes it’s not enough to locate an element. For example, we want to find the display format for Korea. If we user _near to find element, we may find the Data element. But with _under as another restrict, we are able to locate the element from two dimensions exactly. We can describe the element in this way, the cell which is near Korea and under display, then we can get the cell near _cell(“Korea”) and under _cell(“Display”).

_cell(0, _near(_cell(“Korea”)), _under(_cell("Display")));

“0” means the nearest cell of cell Korea and also under cell Display. We can change the index to locate the second nearest element and even more indexes in this way.top^


Sahi also provides the ability to handle downloaded files. Our system needs to verify that an excel report can be downloaded and the downloaded file name should be checked.

To assert the downloaded report name, we can use _lastDownloadedFileName in Sahi. So before we start to click Download Report Button, we need to use _clearLastDownloadedFileName to clear the last downloaded file. Then we check whether the last downloaded file name is cleared, if it is true, we click Download Report button to do the downloading. After downloading is done, we can assert whether the downloaded file has the correct name. See the following code for detail:

_clearLastDownloadedFileName();  while(!_lastDownloadedFileName())
_assertEqual("siteusagereport.action", _lastDownloadedFileName());


_parentTable() and _parentNode() can help to locate the upper level element. In our system, we want to click download button until the search is done then the download button is available for clicking. When button is available, the upper level table will change the class from disable to able.

So in the case above, we get the parent table of view report button and check the class has no x-item-disabled which means the download button is ready for clicking. The code would be like this way:

_wait(5000,_parentTable(_button("View Report")).getAttribute("class").indexOf('x-item-disabled') < 0);


With these four examples, we have shown that Sahi is quite flexible for automation testing, in particular for ExtJS based websites.

Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.

Keep up to date with our latest insights