How to verify dynamic table through assertion in selenium java - java

I have tried for one by one raw like this
String element= driver.findElement(By.xpath("//*[#id='historyRow']/tbody/tr[1]/td[1]")).getText();
Assert.assertEquals(element, auto);
Here is Html code:
I want to verify that Add a second value in table and verify that all details are displayed for each value with previous value added first.
How to verify for all raw
Is there any other way rather than one by one
<table id="historyRow">
<thead>
<tr style="cursor: pointer;">
<th class="portlet-section-header descending">
Date and Time</th>
<th class="portlet-section-header">
User</th>
<th class="portlet-section-header">
Action</th>
<th class="portlet-section-header">
Description / Comment</th></tr></thead>
<tbody>
<tr class="portlet-section-body" style="cursor: pointer;">
<td>
Nov 19, 2019 09:34:10 AM EST
</td>
<td>
<!-- This hack is needed just for requests which had this audit comment inserted by their rule execution -->
<!-- New requests won't have this comment anymore -->
abc,auto
</td>
<td>
Edit
</td>
<td>
<table style="width: auto;">
<tbody><tr style="cursor: pointer;"><td align="left" style="border-spacing:1px; padding-top:0px; padding-right:3px; padding-bottom:0px; padding-left:0px;">
<table style="border-spacing:1px; padding-top:0px; padding-right:3px; padding-bottom:0px; padding-left:0px; width: auto;">
<tbody><tr style="cursor: pointer;">
<td align="left" style="border-spacing:1px; padding-top:0px; padding-right:3px; padding-bottom:0px; padding-left:0px; vertical-align:text-top; text-align:left;">
<b>Comment</b>
</td>
<td style="border-spacing:1px; padding-top:0px; padding-right:3px; padding-bottom:0px; padding-left:0px;">
Add Comment. comment
</td>
</tr>
</tbody></table>

Try the below code :
Please check the closing of braces.
// Grab the table
WebElement table = driver.findElement(By.id("View"));
//get the size of the list of the rows
List<WebElement> totalRows = table.findElements(By.tagName("tr"));
int rows_count = totalRows.size();
//Loop will execute till the last row of table.
for (int row=0; row<rows_count; row++){
//To locate columns(cells) of that specific row.
List<WebElement> Columns_row = rows_table.get(row).findElements(By.tagName("td"));
//To calculate no of columns(cells) In that specific row.
int columns_count = Columns_row.size();
System.out.println("Number of cells In Row "+row+" are "+columns_count);
//Loop will execute till the last cell of that specific row.
for (int column=0; column<columns_count; column++){
//To retrieve text from that specific cell.
String celtext = Columns_row.get(column).getText();
System.out.println("Cell Value Of row number "+row+" and column number "+column+" Is "+celtext);
}
});

Related

How to get table data from a selenium webelement and check column value

In my selenium script , I want to get the table data from below table, and compare all values under column 'phone' and check if all the values are only numeric.
I tried to use the following code, if is not printing the text of each column, instead it is displaying number of rows.
WebElement table = driver.findElement(By.xpath(“//table[contains(#class, 'table table-style')]”));
List<WebElement> rowsList = table.findElements(By.tagName("tr"));
List<WebElement> columnsList = null;
for (WebElement row : rowsList) {
columnsList = row.findElements(By.tagName("td"));
for (WebElement column : columnsList) {
System.out.println("column text" + column.getText()+ ", "); // here is is just printing number of rows, like 1, 2
}
}
<table class="table table-style" >
<thead>
<tr>
<th class="text-center">
Id
</th>
<th class="text-center">username</th>
<th class="text-center">email</th>
<th class="text-center">phone</th>
<th class="text-center">address1</th>
<th class="text-center">address2</th>
<th class="text-center">City</th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center">Here is user name</td>
<td class="text-center">email#email.com</td>
<td class="text-center">123456789</td>
<td class="text-center">address 1</td>
<td class="text-center">address 2</td>
<td class="text-center">city name</td>
</tr>
<tr>
<td class="text-center">Here is user name</td>
<td class="text-center">email#email.com</td>
<td class="text-center">99999999</td>
<td class="text-center">address 1</td>
<td class="text-center">address 2</td>
<td class="text-center">city name</td>
</tr>
<tr>
<td class="text-center">Here is user name</td>
<td class="text-center">email#email.com</td>
<td class="text-center">abcdef12</td>
<td class="text-center">address 1</td>
<td class="text-center">address 2</td>
<td class="text-center">city name</td>
</tr>
</table>
Get the cell value by the column name
There is no any additional attributes in your case to detect that some cell belongs to some column.
I suggest to detect the column number by text using XPATH count method, and use it for getting all cells by column.
For the phone column:
List<WebElement> phoneNumbersList = table.findElements(By.xpath("//td[count(//th[text()='phone']/preceding-sibling::th)]"));
// the same can be dome for "email" and other columns.
Check if all the values are only numeric
Look at this:
Java String - See if a string contains only numbers and not letters
I tried to use the following code, if is not printing the text of each column, instead it is displaying number of rows.
I can confirm that this code:
#Test
public void printTable() {
WebDriver driver = new ChromeDriver(new ChromeOptions());
driver.manage().window().maximize();
//local html file
driver.get("file:///D:/projects/print-table/src/test/resources/test.html");
WebElement table = driver.findElement(By.xpath("//table[contains(#class, 'table table-style')]"));
List<WebElement> rowsList = table.findElements(By.tagName("tr"));
List<WebElement> columnsList = null;
for (WebElement row : rowsList) {
columnsList = row.findElements(By.tagName("td"));
for (WebElement column : columnsList) {
System.out.println("column text" + column.getText()+ ", "); // here is is just printing number of rows, like 1, 2
}
}
driver.quit();
}
Prints:
column textHere is user name,
column textemail#email.com,
column text123456789,
column textaddress 1,
column textaddress 2,
column textcity name,
column textHere is user name,
column textemail#email.com,
column text99999999,
column textaddress 1,
column textaddress 2,
column textcity name,
column textHere is user name,
column textemail#email.com,
column textabcdef12,
column textaddress 1,
column textaddress 2,
column textcity name,
So, your provided snippet works as expected.

How can I count and select some rows in a Web table using Selenium?

I'm developing an Automation test using Selenium WebDriver and Java, I need to assured that there are items in the web table, and select one of those items, but the ID is dynamic.
HTML code:
<table class="datagrid-btable" cellspacing="0" cellpadding="0" border="0" style="table-layout: auto;"> <tbody>
<tr id="datagrid-row-r4-2-0" datagrid-row-index="0" class="datagrid-row datagrid-row-selected">
<td field="PLANT_CODE" style="display:none;">
<div style="text-align: left;" class="datagrid-cell datagrid-cell-c4-PLANT_CODE">1001</div>
</td>
<td field="PLANT_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-PLANT_NM">TESTE1</div>
</td>
<td field="PU_NAME" style="display:none;">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-PU_NAME"></div>
</td>
<td field="SUPPLIER_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_CODE">SUP001AR</div>
</td>
<td field="SUPPLIER_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_NM">SUPPLIER 001 AR</div>
</td>
<td field="ITEM_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ITEM_CODE">ITEM001AR</div>
</td>
<td field="ITEM_NM">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-ITEM_NM">ITEM1 AR</div>
</td>
<td field="WRHOUSNG_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-WRHOUSNG_NO"></div>
</td>
<td field="ORDE_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ORDE_NO"></div>
</td>
</tr>
<tr id="datagrid-row-r4-2-1" datagrid-row-index="1" class="datagrid-row">
<td field="PLANT_CODE" style="display:none;">
<div style="text-align: left;" class="datagrid-cell datagrid-cell-c4-PLANT_CODE">1001</div>
</td>
<td field="PLANT_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-PLANT_NM">BOCAR LERMA</div>
</td>
<td field="PU_NAME" style="display:none;">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-PU_NAME"></div>
</td>
<td field="SUPPLIER_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_CODE">SUP001AR</div>
</td>
<td field="SUPPLIER_NM">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-SUPPLIER_NM">SUPPLIER 001 AR</div>
</td>
<td field="ITEM_CODE">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ITEM_CODE">ITEM001AR</div>
</td>
<td field="ITEM_NM">
<div style=";text-align:left;" class="datagrid-cell datagrid-cell-c4-ITEM_NM">ITEM1 AR</div>
</td>
<td field="WRHOUSNG_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-WRHOUSNG_NO">PUR1</div>
</td>
<td field="ORDE_NO" style="display:none;">
<div style=";text-align:center;" class="datagrid-cell datagrid-cell-c4-ORDE_NO">PUR1</div>
</td>
</tr> </tbody> </table>
I tried "My code":
WebElement tbody = driver.findElement(By.xpath("//*[#class='datagrid-body']/tbody/tr"));
In this case, my request is returning two rows so how can I count the rows and select one of these?
Thanks
Try this step for get you want.
1. Table initialize
In your case, the table has the class datagrid-btable, the way to initialize it :
WebElement tbl = driver.findElement(By.className("datagrid-btable"));
2. Row initialize
The name tag for the web table row in general is tr, the way to initialize it :
List<WebElement> rows = tbl.findElements(By.tagName("tr"));
You can get rowCount with :
int count = rows.size();
System.out.println("count rows :" +count);
3. Column initialize
The name tag for the web table column in general are th or td, the way to initialize it :
td tag
List<WebElement> cols = rows.get(rowIndex).findElements(By.tagName("td"));
So you can select particular cell by :
String cell = cols.get(indexCol).getText();
Example for select col1 in row1 :
List<WebElement> cols = rows.get(0).findElements(By.tagName("td"));
String cell = cols.get(0).getText();
System.out.println("cell value :" +cell);
Or try this iteration for select all cell table :
for(int i=0; i<rows.size(); i++) {
//check column each in row, identification with 'td' tag
List<WebElement> cols = rows.get(i).findElements(By.tagName("td"));
//column iteration
for(int j=0; j<cols.size(); j++) {
System.out.println("row " +(i+1) +" col " +(j+1) +" : " +cols.get(j).getText());
}
}
You can get count of the rows using findElements method:
List<WebElement> rows = driver.findElements(By.cssSelector(".datagrid-btable tr.datagrid-row"));
System.out.println(rows.size());
Easy way to select row with specific text using xpath:
// get row contains text 1001
driver.findElement(By.xpath("//table[#class='datagrid-btable']//tr[#class='datagrid-row' and contains(.,'1001')]")).click();
// get row by PLANT_CODE and exact cell value
driver.findElement(By.xpath("//table[#class='datagrid-btable']//tr[#class='datagrid-row' and .//td[#field='PLANT_CODE' and div[text()='1001']]]")).click();
To find row you need, you can use stream().filter(). In the example below, rows filtered by PLANT_NM text. Using filter or rows iteration, you can write a method to filter rows by any/multi cells:
List<WebElement> rows = driver.findElements(By.cssSelector(".datagrid-btable tr.datagrid-row"));
System.out.println(rows.size());
List<WebElement> filteredRows = rows.stream().filter(element ->
element.findElement(By.cssSelector("td[field='PLANT_NM'")).getText().equals("BOCAR LERMA"))
.collect(Collectors.toList());
Assert.assertTrue(filteredRows.size() > 0, "Row with \"BOCAR LERMA\" PLANT_NM exist.");
filteredRows.get(0).click();

java find table using jsoup and equivalent xpath

Here is the HTML code:
<table class="textfont" cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
<tbody>
<tr>
<td class="chl" width="20%">Batch ID</td><td class="ctext">d32654464bdb424396f6a91f2af29ecf</td>
</tr>
<tr>
<td class="chl" width="20%">ALM Server</td>
<td class="ctext"></td>
</tr>
<tr>
<td class="chl" width="20%">ALM Domain/Project</td>
<td class="ctext">EBUSINESS/STERLING</td>
</tr>
<tr>
<td class="chl" width="20%">TestSet URL</td>
<td class="ctext">almtestset://localhost</td>
</tr>
<tr>
<td class="chl" width="20%">Tests Executed</td>
<td class="ctext"><b>6</b></td>
</tr>
<tr>
<td class="chl" width="20%">Start Time</td>
<td class="ctext">08/31/2017 12:20:46 PM</td>
</tr>
<tr>
<td class="chl" width="20%">Finish Time</td>
<td class="ctext">08/31/2017 02:31:46 PM</td>
</tr>
<tr>
<td class="chl" width="20%">Total Duration</td>
<td class="ctext"><b>2h 11m </b></td>
</tr>
<tr>
<td class="chl" width="20%">Test Parameters</td>
<td class="ctext"><b>{"browser":"chrome","browser-version":"56","language":"english","country":"US"}</b></td>
</tr>
<tr>
<td class="chl" width="20%">Passed</td>
<td class="ctext" style="color:#269900"><b>0</b></td>
</tr>
<tr>
<td class="chl" width="20%">Failed</td>
<td class="ctext" style="color:#990000"><b>6</b></td>
</tr>
<tr>
<td class="chl" width="20%">Not Completed</td>
<td class="ctext" style="color: ##ff8000;"><b>0</b></td>
</tr>
<tr>
<td class="chl" width="20%">Test Pass %</td>
<td class="ctext" style="color:#990000;font-size:14px"><b>0.0%</b></td>
</tr>
</tbody>
And here is the xpath to get the table:
//td[text() = 'TestSet URL']/ancestor::table[1]
How can I get this table using jSoup? I've tried:
tableElements = doc.select("td:contains('TestSet URL')");
to get the child element, but that doesn't work and returns null. I need to find the table and put all the children into a map. Any help would be greatly appreciated!
The following code will parse your table into a map, this code is subject to a few assumptions:
This xpath //td[text() = 'TestSet URL']/ancestor::table[1] will find any table which contains the text "TestSet URL" anywhere in its body, this seems a little bit brittle but assuming it is sufficient for you the JSoup code in getTable() is functionally equiavalent to that xpath
The code below assumes that every row contains two cells with the first one being the key and the second one being the value, since you want to parse the table content to a map this assumption seems valid
The code below throws exceptions if the above assumptions are not met i.e. if the given HTML does not contain a table definition with "TestSet URL" embedded in its body or if there are more than two cells in any row within that table.
If those assumptions are invalid then the internals of getTable and parseTable will change but the general approach will remain valid.
public void parseTable() {
Document doc = Jsoup.parse(html);
// declare a holder to contain the 'mapped rows', this is a map based on the assumption that every row represents a discreet key:value pair
Map<String, String> asMap = new HashMap<>();
Element table = getTable(doc);
// now walk though the rows creating a map for each one
Elements rows = table.select("tr");
for (int i = 0; i < rows.size(); i++) {
Element row = rows.get(i);
Elements cols = row.select("td");
// expecting this table to consist of key:value pairs where the first cell is the key and the second cell is the value
if (cols.size() == 2) {
asMap.put(cols.get(0).text(), cols.get(1).text());
} else {
throw new RuntimeException(String.format("Cannot parse the table row: %s to a key:value pair because it contains %s cells!", row.text(), cols.size()));
}
}
System.out.println(asMap);
}
private Element getTable(Document doc) {
Elements tables = doc.select("table");
for (int i = 0; i < tables.size(); i++) {
// this xpath //td[text() = 'TestSet URL']/ancestor::table[1] will find the first table which contains the
// text "TestSet URL" anywhere in its body
// this crude evaluation is the JSoup equivalent of that xpath
if (tables.get(i).text().contains("TestSet URL")) {
return tables.get(i);
}
}
throw new RuntimeException("Cannot find a table element which contains 'TestSet URL'!");
}
For the HTML posted in your question, the above code will output:
{Finish Time=08/31/2017 02:31:46 PM, Passed=0, Test Parameters={"browser":"chrome","browser-version":"56","language":"english","country":"US"}, TestSet URL=almtestset://localhost, Failed=6, Test Pass %=0.0%, Not Completed=0, Start Time=08/31/2017 12:20:46 PM, Total Duration=2h 11m, Tests Executed=6, ALM Domain/Project=EBUSINESS/STERLING, Batch ID=d32654464bdb424396f6a91f2af29ecf, ALM Server=}
You have to remove those quotation marks to get the row with the text; just
tableElements = doc.select("td:contains(TestSet URL)");
but note with the above you are only selecting td elements which contain the text "TestSet URL". To select the whole table use
Element table = doc.select("table.textfont").first();
which means select table with class=textfont and to avoid selecting multiple tables which can have the same class value you have to specify which to choose, therefore: first().
To get all the tr elements:
Elements tableRows = doc.select("table.textfont tr");
for(Element e: tableRows)
System.out.println(e);

How to select current date+1 from date picker popup, without using sendkeys

Using selenium web-driver Java, I want to select current date+1 from date popup, I have seen other post related to date picker but they are related to current date only or else using sendkeys. I don't want to use sendkeys.
Below is the HTML code
'<table id="dp_cal_calendar" class="calendar" classname="calendar" style="display: block; position: absolute; top: 282px; left: 574px;">
<tbody>
<tr>
<tr>
<td>
<table class="cells" classname="cells">
<thead class="caldayheading" classname="caldayheading">
<tbody>
<tr>
<tr>
<tr>
<tr>
<td class="wkend" classname="wkend">20</td>
<td class="wkend" classname="wkend">21</td>
<td class="wkday" classname="wkday">22</td>
<td class="wkday" classname="wkday">23</td>
<td class="wkday" classname="wkday">24</td>
<td class="wkday curdate" classname="wkday curdate">25</td>
<td class="wkday" classname="wkday">26</td>
</tr>
<tr>
<tr>
</tbody>
</table>
</td>
</tr>
<tr>
</tbody>
</table>'
Assuming ur date picker calendar is in table format
you can use:
public void checkDate(){
String currentDate = null;
int counter=0;
WebElement tab = driver.findElement(By.id("tabid"));
List<WebElement> rows= tab.findElements(By.tagName("tr"));
for(int i =0;i<=rows.size()-1;i++){
List<WebElement> columns=rows.get(i).findElements(By.tagName("td"));
Iterator itr = columns.iterator();
while(itr.hasNext()){
WebElement we=(WebElement) itr.next();
if(we.getText().equals(currentDate)){
break;
}
counter=counter+1;
}
//element to be clicked is +1 to c
driver.findElement(By.cssSelector("tr:nth-child(i) li:nth-child(counter+1)")).click();
}
PS. This should serve your purpose but you need to handle the case when your current date is in last column of the table.
UPDATE:
String currDate= driver.findElement(By.cssSelector("table#dp_cal_calendar table.cells td.wkday.curdate")).getText();
int dateToBeSelected = Integer.parseInt(currDate) + //no of days you want to add ;
WebElement currentDate = driver.findElement(By.xpath("//table[#id='dp_cal_calendar']//table[#class='cells']//td[contains(text(),'"+String.valueOf(dateToBeSelected) +"')]")).click();

How to get number of columns <td> or <th> in a row <tr>?

I want to get the number of columns in a given row, when I use below snippet
int size = element.findElement(By.xpath("/tr[" + Row + "]")).findElements(By.tagName("td")).size();
I get an exception stating NoSuchElementException.
Below is the HTML block
<table class="DynamicOrderTable" id="customerOrderHeader">
<tbody>
<tr style="background-color: rgb(246, 246, 246);">
<th>Order Number</th>
<th>Version</th>
<th>Customer Name</th>
<th>Order Status</th>
<th>Order Sub-status</th>
</tr>
<tr class="Temp">
<td class="close" id="orderNumber">
<div class="clickableText">1234</div>
</td>
<td class="close">1</td>
<td class="close" id="customerName">ABC101</td>
<td title="OrderResponse Sequence Number:14" class="close" id="orderStatus"><div class="clickableText">Complete</div></td>
<td class="close">Closed</td>
</tr>
</tbody>
</table>
How to get the number of columns in a row when we have thead and tbody tags?
Your code to get column size is correct, just change /tr to .//tr in your xpath as :-
WebElement element = driver.findElement(By.id("customerOrderHeader"));
int size = element.findElement(By.xpath(".//tr[" + Row + "]")).findElements(By.tagName("td")).size();
Or
int size = element.findElements(By.tagName("tr")).get(Row).findElements(By.tagName("td")).size();
If I understood your question correctly, code below should help you to get no. of columns.
Using XPath
int size = driver.findElements(By.xpath("//*[#id="customerOrderHeader"]/tbody/tr[1]/th")).size();
Using CssSelector
int size = driver.findElements(By.cssSelector("table#customerOrderHeader>tbody>tr:first-child>th")).size();
Try the below Code:
int count =driver.findElements(By.xpath(".//tr[#class='Temp']//td")).size();
System.out.println("count is "+count);//output is count is 5
use cells property with row index
document.getElementById("customerOrderHeader").rows[0].cells.length;

Categories