简体   繁体   中英

Select nested element by text using cssSelector - Selenium WebDriver

I am trying to select an element based on the text. The problem I'm having is the element text exists multiple times in the source code. I was using xpath to find it (even though I try to avoid xpath), but that's all that I could get working.

Here is the html I'm working against:

<ul id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage" class="cbl centered d2" style="width:511px;">
    <li>
        <input id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_0" name="ctl00$ctl00$Dialogs$Dialogs$ctlAcknowledgeMessage_ConditionalDecline$cblMessage$0" onclick="CannedCommentSelected(this);" value="Complexity of job requires extra charge" type="checkbox">
        <label for="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_0">Complexity of job requires extra charge</label>
    </li>
    <li>
        <input id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_1" name="ctl00$ctl00$Dialogs$Dialogs$ctlAcknowledgeMessage_ConditionalDecline$cblMessage$1" onclick="CannedCommentSelected(this);" value="Complexity of job requires extra time" type="checkbox">
        <label for="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_1">Complexity of job requires extra time</label>
    </li>
    <li>
        <input id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_2" name="ctl00$ctl00$Dialogs$Dialogs$ctlAcknowledgeMessage_ConditionalDecline$cblMessage$2" onclick="CannedCommentSelected(this);" value="Current workload requires extra time" type="checkbox">
        <label for="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_2">Current workload requires extra time</label>
    </li>
    <li>
        <input id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_3" name="ctl00$ctl00$Dialogs$Dialogs$ctlAcknowledgeMessage_ConditionalDecline$cblMessage$3" onclick="CannedCommentSelected(this);" value="Distance to property requires extra charge" type="checkbox">
        <label for="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_3">Distance to property requires extra charge</label>
    </li>
</ul>

I was using driver.findElement(By.xpath("//label[contains(text(), 'Complexity of job requires extra charge')]")); but I started getting the "Element is not currently visible and so may not be interacted with" error which led me to discover there are multiple labels with the "Complexity of job requires extra charge" text.

I tried driver.findElement(By.cssSelector("#Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage > #Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_0 > label[text='Complexity of job requires extra charge']")); but it timed out trying to find the element.

What am I doing wrong?

I even tried driver.findElement(By.cssSelector("#Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage > input[value='Complexity of job requires extra charge']")); which I was sure would work, but it times out looking for that also.

In this case you should try using JavascriptExecutor to interact with this as below :-

WebElement el = driver.findElement(By.cssSelector("input[value='Complexity of job requires extra charge']"));

((JavascriptExecutor) driver).executeScript("arguments[0].click();",el);

Edited :-

List<WebElement> els = driver.findElements(By.cssSelector("input[value='Complexity of job requires extra charge']"));
for(WebElement el : els) 
{
  if(el.isDisplayed() && el.isEnabled())
  {
   el.click();
  }
}

Hope it helps...:)

You have two problems with the cssSelector :

> is used for direct child, but the elements with id that ends with cblMessage and cblMessage_0 have another element between them, and the element with id that ends with cblMessage_0 and the element you are looking for are siblings.

You can use this cssSelector to locate the element with the text

driver.findElement(By.cssSelector("#Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage_0 ~ label"));

~ represents sibling.

Your CSS didn't work because it's trying to find the label as a child of the input, which is really a sibling. You can tell xpath to find that parent ul by ID too. The following XPath should work:

//ul[@id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage"]/li/label[contains(text(), 'Complexity of job requires extra charge')]

and if you're actually interested in selecting the input so that you can check that box, try this:

//ul[@id="Dialogs_Dialogs_ctlAcknowledgeMessage_ConditionalDecline_cblMessage"]/li/label[contains(text(), 'Complexity of job requires extra charge')]/preceding-sibling::input

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM