For example, for the page below, there is a ListView to display the rows. In each row the user can input a value into "v" and click the submit button. Then the total value of the rows will be displayed at the end of the page:
<html>
<body>
<table>
<tr wicket:id="eachRow">
<td>
<form wicket:id="f">
<input wicket:id="v" type="text">
<input wicket:id="ok" type="submit">
</form>
</td>
</tr>
</table>
<span wicket:id="container">
<span wicket:id="total">333</span>.
</span>
</body>
</html>To locate, say, the "total" <span>, use a locator wicket=//total with Selenium, meaning to search deep any level into the document root element (<html>) for an HTML element with wicket:id="total":
@Test
public class PageExtractedByWicketIdsTest {
public void testWicketLocator() {
DefaultSelenium selenium = WebPageTestContext.getSelenium();
WicketSelenium ws = new WicketSelenium(selenium);
ws.openBookmarkablePage(...);
assert selenium.getText("wicket=//total").equals("0");
}
}If you use wicket=/total instead, it will only search the immediate children of the <html> element, which will not work here as the <span> is many levels deep inside <html>.
How to input something into, say, the "v" text field in the first row (<tr>)? First, you locate the first <tr> with wicket=//eachRow. As there are many rows, it is better to explicitly write wicket=//eachRow[0]. Then you can search inside the <tr> for "v" with wicket=//eachRow[0]//v. It is similar for the other rows:
@Test
public class PageExtractedByWicketIdsTest {
public void testWicketLocator() {
DefaultSelenium selenium = WebPageTestContext.getSelenium();
WicketSelenium ws = new WicketSelenium(selenium);
ws.openBookmarkablePage(...);
assert selenium.getValue("wicket=//eachRow[0]//v").equals("3");
assert selenium.getValue("wicket=//eachRow[1]//v").equals("2");
assert selenium.getValue("wicket=//eachRow[2]//v").equals("8");
assert selenium.getText("wicket=//total").equals("13");
selenium.type("wicket=//eachRow[1]//v", "5");
selenium.click("wicket=//eachRow[1]//ok");
ws.waitUntilAjaxDone();
assert selenium.getText("wicket=//total").equals("16");
}
}When you specify an index like //eachRow[index], the search is done in a breadth first manner. It means that even if you have embedded loops like:
<html>
<body>
<table>
<tr wicket:id="eachRow">
<td>
<table>
<tr wicket:id="eachRow">
<td>...</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>Conceptually they will be numbered like below. Therefore, it is very easy to locate, say, the 2nd row with //eachRow[2]. It will work no matter how many sub-rows there are in the 0th or 1st row. To locate, say, the 0th row in the 2nd row, use //eachRow[2]//eachRow[0].
<html>
<body>
<table>
<tr> <== //eachRow[0]
<td>
<table>
<tr>
<td>...</td>
</tr>
<tr>
<td>...</td>
</tr>
...
</table>
</td>
</tr>
<tr> <== //eachRow[1]
<td>
<table>
<tr>
<td>...</td>
</tr>
<tr>
<td>...</td>
</tr>
...
</table>
</td>
</tr>
<tr> <== //eachRow[2]
<td>
<table>
<tr>
<td>...</td>
</tr>
<tr>
<td>...</td>
</tr>
...
</table>
</td>
</tr>
</table>
</body>
</html>