Locating HTML elements

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() {
                WicketSelenium ws = WebPageTestContext.getWicketSelenium();
                ws.openBookmarkablePage(...);
                ...
                assert ws.getText(new ByWicketIdPath("//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() {
                WicketSelenium ws = WebPageTestContext.getWicketSelenium();
                ws.openBookmarkablePage(...);
                assert ws.getValue(new ByWicketIdPath("//eachRow[0]//v")).equals("3");
                assert ws.getValue(new ByWicketIdPath("//eachRow[1]//v")).equals("2");
                assert ws.getValue(new ByWicketIdPath("//eachRow[2]//v")).equals("8");
                assert ws.getText(new ByWicketIdPath("//total")).equals("13");
                WebElement v1 = ws.findWicketElement("//eachRow[1]//v");
                v1.clear();  // clear the existing value first
                v1.sendKeys("5"); // input "5"
                WebElement ok = ws.findWicketElement("//eachRow[1]//ok");
                ok.click();
                ws.waitUntilAjaxDone();
                assert ws.getText(new ByWicketIdPath("//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>