How can I loop through checkboxes and select only the ones that are not already selected?

I am working on a script which find checkboxes in a list and then I want to only click the checkboxes where the checkboxes are not selected.
image

I can find that there are 3 checkboxes available

Code:

WebDriver driver = DriverFactory.getWebDriver()

WebElement subcheckboxes = driver.findElement(By.xpath(‘//*[contains(@class, 'PaneContents-container-ReviewPane-container')]’))

List subchckbxs = subcheckboxes.findElements(By.xpath(‘//[contains(@class, 'ProgenitorContainer')]/ul/li/ul/div/div/div[]/div[2]/span’))
println('No. of sub checkboxes: ’ + subchckbxs.size())
String subcntrls = new String[subchckbxs.size()]

Output:
No. of sub checkboxes: 3

For the above situation, I would like to be able to skip the first checkbox and then select the second and third checkbox.

The loop I wrote:

int i=0;
for(WebElement a: subchckbxs)
{
String subattr = WebUI.getAttribute(findTestObject(‘Object Repository/target_Terms/sub_Checkbox’), ‘data-review-control-is-reviewed’)
println(subattr)

  	if(subattr.equals('false'))
  		{
  			 subcntrls[i]=a.click()
      }
  	else
  	{
  		WebUI.comment('This one is selected')
  	}
  			 i++

}

The process is checking 3 times and coming back with 3 trues, I am having a hard time writing the test object path so that it doesn’t just “look” at the first checkbox

//[contains(@class, “PaneContents-container-ReviewPane-container”)]/div/div/ul/li[starts-with(@id,‘mui’)]/ul/div/div/div[]/div[2]/span/span/button

HTML:

Checkbox 1

The paths under the div class=“tss-ov1zod-GroupItemInline-root mui-bas6gm” are the same to get to the button data review control is reviewed attribute.

Thanks

There is a statement to verify if a checkbox, or radio button, is checked, or not, like

if (WebUI.verifyElementChecked(findTestObject('...'), 10)) {

or

if (WebUI.verifyElementNotChecked(findTestObject('...'), 10)) {

As for getting a pathway to your elements, there are a variety of statements to build a pathway, like parent, sibling, preceding and following. I see the labels, 1, 2, and 3, so you should be able to build a pathway from each label to its associated checkbox.

Using Selenium:

if (!button.isSelected()) {

Thanks, for the labels are you referring to Checkbox 1, Checkbox 2 and Checkbox 3 in red from the image? I added the text there in the screenshot to show the 3 checkboxes paths.

image

ok, I changed those from what is actually there (proprietary info). Unfortunately, the labels will not be consistent

also the number of checkbox will be inconsistent. So I need to capture the number of checkboxes, ignore the checkboxes that are already selected and then select the checkboxes that are not selected.

I did try verifyElementChecked but I still see the same results. I realize that the loop is running 3 times because that is the number of checkboxes but I am still stuck on moving off the first checkbox (without clicking it) to the next checkbox and clicking it.

Your first reference above will get you the number of checkboxes. Then you loop checking whether the second reference is true.

Maybe like:

Using something like you have:

List<WebElement> myCheckBoxes = driver.findElements('//div[@class="tss-ov1zod-GroupItemInline-root mui-bas6gm"]')

WebUI.comment("number of boxes is ${myCheckBoxes.size().toString()}")

for (int cnt = 0; cnt < myCheckBoxes.size(); cnt++) {
    WebElement myButton = myCheckBoxes.get(cnt).findElement(By.xpath('//div[2]/span[1]/span[1]/button'))

    String subattr = myButton.getAttribute('data-review-control-is-reviewed')

    if (subattr != 'true') {  // maybe you can equal false after testing
        WebUI.comment("Button ${cnt.toString()} is off")
        myButton.click();
        WebUI.verifyMatch(myButton.isSelected().toString(), "true", false)
    } else {
       WebUI.comment("Button ${cnt.toString()} is on")
       WebUI.verifyMatch(myButton.isSelected().toString(), "true", false) // do we want this
    }
}

Thank you for your help, had to change the path below

WebElement myButton = myCheckBoxes.get(cnt).findElement(By.xpath(‘//div[2]/span[1]/span[1]/button’))

to

WebElement myButton = myCheckBoxes.get(cnt).findElement(By.xpath(‘//div[2]/span[1]/span[1]/button[contains(@class, 'ReviewCheckbox-iconButton')]’))

as the script was failing because it was running into an element with the "//div[2]/span[1]/span[1]/button’ further up the app which is disabled.

I seem to be seeing the same results it the comment states “Button 0 is on” which is correct but it also states that “Button 1 is on” and “Button 2 is on”, therefore does not click

Perhaps we shouldn’t use that attribute then to detect if the element is checked or not. It doesn’t seem reliable.

Maybe like:
List<WebElement> myCheckBoxes = driver.findElements('//div[@class="tss-ov1zod-GroupItemInline-root mui-bas6gm"]')

WebUI.comment("number of boxes is ${myCheckBoxes.size().toString()}")

for (int cnt = 0; cnt < myCheckBoxes.size(); cnt++) {
    WebElement myButton = myCheckBoxes.get(cnt).findElement(By.xpath('//div[2]/span[1]/span[1]/button[contains(@class, "ReviewCheckbox-iconButton")]'))

    boolean subattr = myButton.isSelected();

    if (subattr) {
       WebUI.comment("Button ${cnt.toString()} is on")
       WebUI.verifyMatch(myButton.isSelected().toString(), "true", false) // do we want this
    } else {
        WebUI.comment("Button ${cnt.toString()} is off")
        myButton.click();
        WebUI.verifyMatch(myButton.isSelected().toString(), "true", false)
    }
}

Thank you for all of your help. I had to go down one more level in the path and use By.cssSelector because the script would fail with xpath. Not sure why but, the scrip is working as desired.

Have a great weekend.