0

I'm attempting to click a checkbox based on it's adjacent text. However the pages structure is making it rather difficult. The problem is things are nested in tables nested in divs and so on. The section of code in question looks like this:

<tr id="yui-rec62" class="yui-dt-first yui-dt-even" style="">
    <td class="yui-dt25-col-access yui-dt-col-access yui-dt-first" headers="yui-dt25-th-access ">
        <div class="yui-dt-liner">
            <input id="functionId13" type="checkbox" value="13" name="functionId">
        </div>
    </td>
    <td class="yui-dt25-col-name yui-dt-col-name yui-dt-last" headers="yui-dt25-th-name ">
        <div class="yui-dt-liner">Ability to Add/Remove Queues</div>
    </td>
</tr>

I need to be able to find the div containing Ability to Add/Remove Queues by way of the input with the ID of functionId13. This is resulting in a check like this:

if(div has text of "Ability to Add/remove Queues"){
    return the WebElement of the check box associated with it
}

I have a list of all the checkboxes and their IDs, I just can't come up with a way to match them up with their descriptive text.

Artjom B.
  • 58,311
  • 24
  • 111
  • 196
aweeks
  • 1
  • 1

2 Answers2

1

There is no parent selector in CSS and you will need one if you want to select this, but you can do this with XPath:

//input[@id='functionId13']/../../following-sibling::td[1]/div[@class='yui-dt-liner']
  1. //input[@id='functionId13'] selects the input
  2. /../.. goes up to the first td
  3. /following-sibling::td[1] gives the td after the current node
  4. and /div[@class='yui-dt-liner'] selects the div in the second td

In java it would look like this:

boolean found = false;
for(String id : idList) {
    WebElement el = driver.findElement(By.xpath("//input[@id='"+id+"']/../../following-sibling::td[1]/div[@class='yui-dt-liner']"));
    if (el.getText().indexOf("Ability to Add/remove Queues") != -1) {
        found = true;
        break;
    }
}
// do something with `found`

The XPath for doing it backwards would look like this:

WebElement input = driver.findElement(By.xpath(
    "//div[contains(text(),'Ability to Add/Remove Queues')]"+
    "/../preceding-sibling::td[1]"+
    "//input[@name='functionId']"
));
Community
  • 1
  • 1
Artjom B.
  • 58,311
  • 24
  • 111
  • 196
  • I can't hard code the functionId13 because it's dynamic. I think I almost need to do this in reverse almost, but using the text of the div as a starting point, as it's the only thing I can know for sure. – aweeks Jul 31 '14 at 21:35
  • @aweeks You said that you have a list of checkboxes and their IDs. Iterate over the IDs and check if one of the returned divs found via the IDs matches the text. – Artjom B. Jul 31 '14 at 21:42
  • @aweeks I added an example for iteration and the backwards walk on the elements. – Artjom B. Jul 31 '14 at 21:57
0

With CSS Selector you will not be able to get that as it does not support this kind of needs.

The only one and easy way is to use XPath as below.

WebElement yourElement = driver.findElement(By.xpath("//div[contains(text(),'Ability to Add/Remove Queues')]");

Or you can get all div's using findElements() and loop them to find the element which has the text that you require.

Purus
  • 5,227
  • 6
  • 40
  • 83
  • I thought of getting all the divs by class, but the page can contain upwards of 300 of them, and it will only grow as time goes on (every dynamically generated thing gets a div with a class of 'yui-dt-liner'). – aweeks Jul 31 '14 at 21:39