Selenium Webdriver - Unticking all the chekboxes in a complicated table - java

I am having some problems currently trying to untick checkboxes in an iframe. The situation is it is currently possible to set some checkboxes to default ticked and some not. I need 1 specific checkbox ticked, so the sensible thing to do is run a loop that iterates through all the checkboxes and unchecks them all.
Here is where I am running into issues. I will post a sample of the HTML that the checkboxes are contained in. (This isn't mine so I can't edit the HTML unfortunately).
This is how the example looks in a situation where there are 3 different types of checkbox in the iframe.
<fieldset id="testing">
<legend>testing</legend>
<table>
<tbody>
<tr>
<td class="EXAMPLE">
<table id="CHECKBOXTYPE1">
<tbody>
<tr>
<td style="vertical-align:top;white-space:nowrap;" title="">
<input id="CHECKBOXTYPE1-01" type="checkbox" value="on" onclick="DOES STUFF;"/>
</td>
<td style="vertical-align:top;white-space:nowrap;" title="">TITLE1</td>
</tr>
<tr>
<td/>
<td id="CHECKBOXTYPE2-01" style="display:none;white-space:nowrap;vertical-align:top;padding:0px;">
<table>
<tbody>
<tr>
<td style="vertical-align:top;" colspan="3">
<select id="field" style="width:100%;">
<option value="1">STUFF1 </option>
<option value="2">STUFF2 </option>
<option value="3">STUFF3 </option>
<option value="4">STUFF4 </option>
</select>
</td>
<td style="vertical-align:bottom;padding-left:6px;" rowspan="2">
<textarea id="CHECKBOXTYPE2-01-COMMENTS" cols="50" rows="2" style="margin:0px;height:50px;" type="text" onclick="DOES STUFF">Please Insert Notes...</textarea>
</td>
</tr>
<tr>
<td style="vertical-align:bottom;">
<input type="CHECKBOXTYPE2-01-BUTTON" onclick="DOES STUFF" value="<" style="height:100%;width:32px;"/>
</td>
<td style="vertical-align:bottom;">
<input id="CHECKBOXTYPE2-01-INPUT" type="input" readonly="" style="width:112px;"/>
</td>
<td style="vertical-align:bottom;">
<input type="CHECKBOXTYPE2-01-BUTTON" onclick="DOES STUFF" style="width:32px;height:100%;" value=">"/>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="field_label">
<table id="CHECKBOXTYPE3">
<tbody>
<tr>
<td style="vertical-align:top;">
<input id="CHECKBOXTYPE3-01" type="checkbox" title="" onclick="DOES STUFF"/>
</td>
<td style="vertical-align:top;" title="">CHECKBOX NAME</td>
<td style="vertical-align:top;">
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
The code I have attempted to iterate is
try{
for(int i=0; i < 30; i++){
WebElement relCheckBoxes = driver.findElement(By.xpath("html/body/div[3]/fieldset/table/tbody/tr[i]/td/table/tbody/tr/td[1]"));
if(relCheckBoxes.isSelected()){
relCheckBoxes.click();
}
}
}
catch(Exception e){
System.out.printf("didn't work");
}
Obviously this is not the most optimised piece of code, but right now I'm just struggling to find something that works :\ I just want to run through the checkboxes, turn off all of them, then turn on the one that I need after.
Thank you.

If you want to uncheck all the checkboxes use the following code. It is much efficient!
//Get the complex table
WebElement mainTable = driver.findElement(By.xpath("html/body/div[3]/fieldset/table"));
//Find all the input tags inside the mainTable and save it to a list
List<WebElement> checkBoxes = mainTable.findElements(By.tagName("input"));
//iterate through the list of checkboxes and if checked, uncheck them
for (WebElement checkbox : checkBoxes) {
if (checkbox.isSelected()) {
checkbox.click();
}
}
I dont see any frame inside your code. If there is a frame use the below code 1st
//switch to the frame
driver.switchTo().frame("framename/index");
Hope this helps you :)

There are a couple of problems here:
1) Your XPath is incorrect. You have:
"html/body/div[3]/fieldset/table/tbody/tr[i]/td/table/tbody/tr/td[1]"
Instead, it should be:
"html/body/div[3]/fieldset/table/tbody/tr[" + i + "]/td/table/tbody/tr/td[1]"
Otherwise, you're just looking for a table row with a non-numerical index 30 times!
2) XPath indices are 1-based rather than 0-based (crazy, I know). Since your loop starts with i=0, it starts off by trying to find the non-existent zeroth element. findElement throws an exception when it cannot locate an element that matches the search criterion, so the loop ends immediately. Try starting the loop with i=1 instead.

Related

Select a row element based on another row element in Selenium

I want to select a checkbox based on another element in the row in Selenium. Eg: How do I select the checkbox corresponding to Cricket?
<body>
<table id="MyTable">
<tbody>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Football</td>
</tr>
<tr>
<td>
<input type="checkbox" />
</td>
<td>Cricket</td>
</tr>
</tbody>
</table>
</body>
Try the following xpath:
driver.findElement(By.xpath("//table[#id='MyTable']//tr[contains(., 'Cricket')]//input[#type='checkbox']")).click();
See check boxes in general are input tag, you if you want to select that using Cricket keyword, you can use the below xpath :
//td[text()='Cricket']/preceding-sibling::td/input
and in code :-
driver.findElement(By.xpath("//td[text()='Cricket']/preceding-sibling::td/input")).click();
or
you could try with Explicit waits as well :
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//td[text()='Cricket']/preceding-sibling::td/input"))).click();

Thymeleaf: th:each for two table rows?

How can I, inside a th:each loop create a group of two rows instead of just one?
I know I can do:
<tr th:each="obj: ${listOfObjects}">
<td>a column with data: ${obj.id}</td>
</tr>
However, I want two <tr> elements to be created, as I would do with JSTL:
<c:forEach items="${listOfObjects}" var="obj">
<tr>
<td>${obj.id}</td>
</tr>
<tr>
<td>${obj.name}</td>
</tr>
</c:forEach>
Is there a way to achieve that with Thymeleaf?
You could use a th:block element for grouping the rows together and repeat them:
<th:block th:each="obj: ${listOfObjects}">
<tr>
<td th:text="${obj.id}"></td>
</tr>
<tr>
<td th:text="${obj.name}"></td>
</tr>
</th:block>
You can read more about th:block here

Selenium Java findElement Query not valid for unique ID or Xpath

I am trying to select the email, password, and signin elements from here.
The element has a unique ID and I'm able to copy the Xpath from inspecting it.
I have tried these queries and unable to figure out why Selenium cannot find it.
WebElement emailfield = driver.findElement(By.id("lid"))
WebElement emailfield = driver.findElement(By.xpath("//*[#id=\'lid\']"));
WebElement emailfield = driver.findElement(By.xpath("//*[#id=lid]"));
The drive is able to open and launch chrome to do this. However, I am not lucky.
Please let me know in what way these are not valid. As I understand it, the id should be completely unique but neither the By.id and By.xpath methods are not finding the element.
Here is my code.
String email = "myemail";
String password = "the_password";
WebElement emailfield = driver.findElement(By.id("lid"));
emailfield.sendKeys(email );
WebElement passwordfield = driver.findElement(By.xpath("//*[#id=pwd]"));
passwordfield.sendKeys(password );
WebElement login = driver.findElement(By.id("submit_but"));
login.click();
Here is HTML table.
<table width="260" align="center" class="mob_width" cellspacing="2" cellpadding="1">
<tbody><tr>
<td colspan="2">
<h3 class="signintxt">Sign In</h3>
</td>
</tr>
<tr>
<td align="center" colspan="2"><span id="msgpanel"></span></td>
</tr>
<tr>
<td class="label">Email / Phone:</td>
<td align="left"><input name="lid" class="input usrbx" id="lid" onkeypress="clearmsg()" type="email" value=""></td>
</tr>
<tr>
<td class="label">Password:</td>
<td align="left"><input name="pwd" class="input passbx" id="pwd" onkeypress="clearmsg()" type="password"></td>
</tr>
<tr>
<td class="label"></td>
<td align="left"><div class="forgotpasslink"><span onclick="goToForgotPassword();">Forgot Password?</span></div>
</td></tr>
<tr id="hiptr" style="display: none;">
<td class="label"> </td><td align="left"> </td>
</tr>
<tr>
<td class="emptytd"></td>
<td height="30" class="mobile-height">
<div class="sectxt">
<label>
<input name="rem" id="rem" type="checkbox" value="10">
<span class="securetxt">Keep me signed in</span>
</label>
</div>
</td>
</tr>
<tr>
<td class="emptytd"></td>
<td align="left">
<button name="submit" class="submit_mobile" id="submit_but" type="submit">Sign In</button>
</td>
</tr>
</tbody></table>
Here is an Explicit wait that compiles, and wait 10 seconds and gives same error.
//explicit
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement aboutMe;
aboutMe= wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(".//form[#id='login']//*[#id='lid']")));
aboutMe.click();
The fields are inside <iframe>. You need to switch to it first
driver.switchTo.frame("zohoiam"); // switch by iframe ID
WebElement emailfield = driver.findElement(By.id("lid"));
// some more code
driver.switchTo().defaultContent(); // switch out of the iframe
For more switch options look here.
You have made syntactical error while writing the xpath,
//*[#id=\'lid\']
has wrong syntax [You can verify this using firebug & firepath].
Try below xpath it should work,
.//*[#id='lid']
However you can add the parent Form node to make it more robust,
.//form[#id='login']//*[#id='lid']
Finally, you need to make sure that you wait till the page is loaded completely before going for element identification.
For more on explicit wait, refer Selenium webdriver explicit wait

struts2 checkboxlist to show aligned label

I have a List<Bill> bills. Bill is a bean that has id, amount, date, billDescription.
I want to display a checkboxlist of Bill objects. So I use:
<s:checkboxlist list="bills" name="selectedBills"
listKey="id" listValue="displayLabel"/>
my Bill.getDisplayLabel() prints out: "amount date billDescription"
40.00 5/1/2011 Electric Bill
1005.25 6/12/2012 Gas Bill
Problem is it is not aligned. I want to customize my displayLabel so that the amounts align up, the dates align up, and the billDescription aligns up. It should display as:
[ ] 40.00 5/1/2011 Electric Bill
[ ] 1005.26 6/12/2012 Gas Bill
with a checkbox in front of each. Essentially I want to generate this code:
<table>
<tr>
<td><input type="checkbox" name="selectedBills" value="9" id="selectedBills-1"/></td>
<td style="text-align: right">40.00</td>
<td>5/1/2011</td>
<td>Electric Bill</td>
</tr>
<tr>
<td><input type="checkbox" name="selectedBills" value="9" id="selectedBills-2"/></td>
<td style="text-align: right">1005.26</td>
<td>6/12/2012</td>
<td>Gas Bill</td>
</tr>
</table>
How do I do this? The first column should have the checkbox, but the last 3 columns are 3 different parts of the label. I tried putting in the <td> code inside my Bill.getDisplayLabel() but struts escapes it so that the actual <td> tags show up!
Any ideas will be appreciated.
updated: I already know how to vertically display the checkboxes by customizing the freemarker templates.
How about using struts iterator? I haven't tested this code properly. But I hope it could give you some idea :
<table>
<s:iterator value="bills" var="bill">
<tr>
<td><input type="checkbox" name="selectedBills" value="${bill.id}" id="selectedBills-2"/></td>
<td style="text-align: right">${bill.amount}</td>
<td>${bill.date}</td>
<td>${bill.description}/td>
</tr>
</s:iterator>
</table>
This is what I ended up using in the end:
<s:iterator value="bills" var="bill" status="rowstatus">
<tr>
<td>
<input type="checkbox" name="selectedBills" value="${bill.id}"
id="selectedBills-${rowstatus.index}" />
</td>
<td style="text-align: right">${bill.amount}</td>
<td >${bill.serviceDate}</td>
<td>${bill.label}</td>
</tr>
</s:iterator>
and this works. The problem with this is, if I have other fields on the JSP that fails validation, this will not work. I'll have to put in additional jstl to make checked="checked" at the end of the <input type="checkbox" ...>

How can recognize user selected which ones?

I have two list on my request on jsp. First one is productGroupName, and the second is products.
Now, I show these like below.
<html:form action="/priceOrder"> <table width="100%" id="tableStyle" style="font: message-box;padding: 20px;">
<logic:iterate id="productGroups" name="productGroup">
<tr>
<td>
<h3 style="background-color: #720D00; color: white;"><bean:write
name="productGroups" property="prodGroupName" /></h3>
<table width="100%" id="tableStyle" style="font: message-box; color: white; padding: 20px; background: #F15A00;">
<tr>
<td width="200px"><strong>Product Name</strong></td>
<td width="100px"><strong>How Many</strong></td>
<td><strong>Info</strong></td>
</tr>
<logic:iterate id="product" name="products">
<tr>
<c:if test="${(productGroups.prodGroupID) == (product.prodGroupID)}">
<td>
<html:checkbox property="productChecked" ><bean:write name="product" property="prodName"/></html:checkbox> <br />
</td>
<td><html:text property="quantity" styleId="check" size="5"/></td>
<td><bean:write name="product" property="prodDesc" /></td>
</c:if>
</tr>
</logic:iterate>
</table>
</td>
</tr>
</logic:iterate>
<tr align="center" style="background-color: #F15A00;"><td height="50px">
<html:submit styleId="buton" property="method"><bean:message key="button.order" /></html:submit>
</td></tr>
<tr><td></td></tr>
</table></html:form>
As you see firstly I iterate productGroupNames, showing if productID is equal to productGroupID under productGroupName. But I have a problem on getting check box and quantity info. I need which product is checked and how many that is wanted.
Instead of doing a form submit directly, submit it through a JS function. In your JS function, since you're iterating your list and giving the checkbox and text field the same name, you'll get an array with the same name.
That is you'll get an array of the IDs. You can get the index of the selected checkbox, get the quantity, get the corresponding list element and populate separate hidden form variables with the value. Then submit it.
An alternative approach would be to have a hidden variable associated with each checkbox which provides some mapping between the list and the checkbox.
I don't do Struts, but their documentation at least says that you need the <html:multibox> for this.

Categories