Example: Locating the Expand Icon in a Dynamic GWT Tree

The Google Widget Toolkit (GWT) is a very popular and powerful toolkit, which is hard to test. The dynamic tree control is a very commonly used UI control in GWT. To expand the tree, we need to identify the Expand icon element.

You can find a sample dynamic GWT tree at http://samples.gwtproject.org/samples/Showcase/Showcase.html#!CwTree.

The default locator generated by Silk4NET is the following:
/BrowserApplication//BrowserWindow//DIV[@id='gwt-debug-cwTree-dynamicTree-root-child0']/DIV/DIV[1]//IMG[@border='0']
For the following reasons, this default locator is no reliable locator for identifying the Expand icon for the control Item 0.0:
  • The locator is complex and built on multiple hierarchies. A small change in the DOM structure, which is dynamic with AJAX, can break the locator.
  • The locator contains an index for some of the controls along the hierarchy. Index based locators are generally weak as they find controls by their occurrence, for example finding the sixth expand icon in a tree does not define the control well. An exception to that rule would be if the index is used to express different data sets that you want to identify, for example the sixth data row in a grid.

Often a good strategy for finding better locators is to search for siblings of elements that you need to locate. If you find siblings with better locators, XPath allows you to construct the locator by identifying those siblings. In this case, the tree item Item 0.0 provides a better locator than the Expand icon. The locator of the tree item Item 0.0 is a stable and simple locator as it uses the @textContents property of the control.

By default, Silk4NET uses the property @id, but in GWT the @id is often not a stable property, because it contains a value like ='gwt-uid-<nnn>', where <nnn> changes frequently, even for the same element between different calls.

You can manually change the locator to use the @textContents property instead of the @id.

Original Locator:
/BrowserApplication//BrowserWindow//DIV[@id='gwt-uid-109']
Alternate Locator:
/BrowserApplication//BrowserWindow//DIV[@textContents='Item 0.0']

Or you can instruct Silk4NET to avoid using @id='gwt-uid-<nnn>'. In this case Silk4NET will automatically record the stable locator. You can do this by adding the text pattern that is used in @id properties to the locator attribute value blacklist. In this case, add gwt-uid* to the blacklist.

When inspecting the hierarchy of elements, you can see that the control Item 0.0 and the Expand icon control have a joint root node, which is a DomTableRow control.

To build a stable locator for the Expand icon, you first need to locate Item 0.0 with the following locator:
/BrowserApplication//BrowserWindow//DIV[@textContent='Item 0.0']
Then you need to go up two levels in the element hierarchy to the DomTableRow element. You express this with XPath by adding /../.. to the locator. Finally you need to search from DomTableRow for the Expand icon. This is easy as the Expand icon is the only IMG control in the sub-tree. You express this with XPath by adding //IMG to the locator. The final stable locator for the Expand icon looks like the following:
/BrowserApplication//BrowserWindow//DIV[@textContent='Item 0.0']/../..//IMG
Or even better, use the XPath ancestor axis to locate the Expand icon:
/BrowserApplication//BrowserWindow//DIV[@textContent='Item 0.0']/ancestor::tr//IMG