0

I have radio buttons that when either radio button is selected, it gets a checked attribute.

This is how the HTML looks:

HTML

My implementation of getting the descendant that has a checked attribute:

public TestObject getCheckedTestObjectFromParent(String parentID){
    WebDriver driver = DriverFactory.getWebDriver()
    WebElement parentWebElement = driver.findElement(By.id(parentID))

    List<WebElement> children = parentWebElement.findElements(By.xpath(".//*"))
    println(children.size())
    for(int i = 0; i < children.size(); i++){
        TestObject childTestObject = getTestObjectFromWebElement(children[i])
        if(WebUI.verifyElementHasAttribute(childTestObject, 'checked', 10, FailureHandling.OPTIONAL)){
            return childTestObject
        }
    }
}

This is the helper method that I use for converting a WebElement to a TestObject :

public TestObject getTestObjectFromWebElement(WebElement element) {
        TestObject object = new TestObject()
        object.addProperty("xpath", ConditionType.CONTAINS, getXPathFromElement(element))
        return object
    }

Helper for getting xpath from WebElement :

protected String getXPathFromElement(WebElement element) {
        String elementDescription = element.toString();
        return elementDescription.substring(elementDescription.lastIndexOf("-> xpath: ") + 10, elementDescription.lastIndexOf("]"));
    }

Am I missing something here or is there something wrong with the WebElement -> TestObject conversion? Also is this possible using only TestObject or only WebElement? If I could get child TestObjects containing certain attributes from a parent TestObject then I wouldn't need to make a mess using WebElements.

Edit

Another image of the HTML, this time with the first radio button checked. As you can see the second radio button no longer has the 'checked' attribute.

HTML2

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
street_jesus
  • 373
  • 5
  • 17
  • @DebanjanB I did ask that, I am trying to get the TestObject with the attribute: 'checked' as you can see from the HTML I provided, only 1 radio button has a 'checked' attribute at a time, and that is the one I want to get. – street_jesus Mar 21 '19 at 16:03
  • Perhaps _Selenium-Java_ clients doesn't have **TestObject** which is well supported in _Katalon_. Hence the counter question. – undetected Selenium Mar 21 '19 at 16:07
  • @DebanjanB I am actually using _Katalon Studio_, and the reason I use **WebElement** is because I could not find a way to get child elements with **TestObjects** and hence the need for converting back to **TestObjects** once I have the **WebElement** I need – street_jesus Mar 21 '19 at 16:10
  • If I have got your question correctly, you are trying to get the **TestObject** which is having the `checked` attribute which is _Katalon_ specific. If getting the relevant _WebElement_ suffice to your need, update the question and I may construct an answer for this question. – undetected Selenium Mar 21 '19 at 16:17
  • @DebanjanB that is exactly what I need, I want to get the **WebElement** that is currently checked, notice it can be either of the 2 radio buttons. – street_jesus Mar 21 '19 at 16:20
  • Additionally, you need to update the question with text based HTML instead of an image. Please read why a [screenshot of HTML or code or error is a bad idea](https://meta.stackoverflow.com/questions/303812/discourage-screenshots-of-code-and-or-errors). Consider updating the Question with formatted text based relevant HTML. – undetected Selenium Mar 21 '19 at 16:38

3 Answers3

1

I was able to fix this by changing (".//*") to (".//*[@checked='checked']")

 parentWebElement.findElement(By.xpath(".//*[@checked='checked']")

will find the element that has the attribute checked = 'checked'

Notice that a list is no longer needed as there can only be 1 checked radio button at a time.

Implementation

public TestObject getCheckedTestObjectFromParent(String parentID){
    WebDriver driver = DriverFactory.getWebDriver()
    WebElement parentWebElement = driver.findElement(By.id(parentID))

    //there is only 1 checked child at a time, so there is no need for a list
    WebElement checkedChild = parentWebElement.findElement(By.xpath(".//*[@checked='checked']"))

    //convert the WebElement to a TestObject and return
    return getTestObjectFromWebElement(checkedChild)
}
street_jesus
  • 373
  • 5
  • 17
1

To retrieve the WebElement that is currently checked you can use either of the following Locator Strategies:

  • cssSelector:

    WebElement elem = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("div.a-toggle.a-toggle--anycase#config-src-laserunits  div[id^='config-src-laserunits-']>input.a-toggle__radio[checked]")));
    
  • xpath:

    WebElement elem = new WebDriverWait(driver, 20).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@class='a-toggle a-toggle--anycase' and @id='config-src-laserunits']//div[starts-with(@id, 'config-src-laserunits-')]/input[@class='a-toggle__radio' and @checked]")));
    
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

Try this Xpath

"//input[@id='config-src-laserunits-wavnmradio' and @checked='checked']"

Example:

List<WebElement> children = driver.findElements(By.xpath("//input[@id='config-src-laserunits-wavnmradio' and @checked='checked']"))

It should return size 1

EDIT

 List<WebElement> children = driver.findElements(By.xpath("//input[@id='config-src-laserunits-wavnmradio']"));
            for (int i=0;i<children.size();i++)
            {
                if(children.get(i).getAttribute("checked")!=null)
                {
                    System.out.println("radio button is checked");
                }
            }
KunduK
  • 32,888
  • 5
  • 17
  • 41
  • this won't work since 'config-src-laserunits-wavnmradio' will not always have the 'checked' attribute, if 'config-src-laserunits-freqthzradio' is selected, then that will have the 'checked' attribute – street_jesus Mar 21 '19 at 16:08
  • so the two input fields that I have, either one can have the 'checked' attribute at a time, and that is the one I am trying to get. – street_jesus Mar 21 '19 at 16:09
  • what are you looking after? Can you elaborate.My initial thought you want that selected radio xpath. – KunduK Mar 21 '19 at 16:14
  • The code is for that only.it will return size 1 instead of 2 radio button. – KunduK Mar 21 '19 at 16:15
  • Sorry if I misunderstood anything. – KunduK Mar 21 '19 at 16:16
  • I am trying to get the radio button that is currently checked, the one that is checked will have a 'checked' attribute. My parent div: 'config-src-laserunits' has 2 child divs that each contain a radio button, I traverse over the children elements to be able to get the element that has the 'checked' attribute, but it seems to not work – street_jesus Mar 21 '19 at 16:18
  • If you try my xpath and give the condition children.size()=1 this will validate also. – KunduK Mar 21 '19 at 16:20
  • it will not because it will only check 1 of the radio buttons, not both, and the one that it will check might have 'checked' attribute or it might not – street_jesus Mar 21 '19 at 16:21
  • I don't think you are understanding what I am saying, there are 2 radio buttons, the other one is 'config-src-laserunits-freqthzradio', when either of these buttons is selected, it will have a checked attribute, otherwise this attribute will not be there, what I am trying to do is find the one that has the checked attribute – street_jesus Mar 21 '19 at 16:34
  • Look at the second HTML I added, you will understand what I am talking about – street_jesus Mar 21 '19 at 16:37
  • @Zymeriath : I think that is what you after.Can you check my updated answer. – KunduK Mar 21 '19 at 16:48
  • I got it fixed by changing (".//*") to (".//*[@checked='checked']") – street_jesus Mar 21 '19 at 16:51
  • If you see my edited answer that is the best way you should do. – KunduK Mar 21 '19 at 16:54