Selenium Chrome WebDriver - fail to get cells list - selenium

I have the following code:
WebElement table = a_chromeWebDriver.findElement(By.className("stats-table"));
List<WebElement> allRows = table.findElements(By.tagName("tr"));
system.out.println(allRows.size());
for (WebElement row : allRows) {
ArrayList<WebElement> cells = (ArrayList<WebElement>) row.findElements(By.tagName("td"));
...
I am executing this code on a similar html like this one:
<table id="table-type-1" class="stats-table stats-main table-1">
<thead>
<tr class="main">
<th class="aaaa" data-type="rank" title="Rank">
</th>
A number of headers here...
</tr>
</thead>
<tbody title="">
<tr bla bla bla>
<td class="bla bla bla" title="bla bla bla>1.</td>
<td class="bla bla bla"></td>
<td class="bla bla bla">36</td>
<td class="bla bla bla">28</td>
<td class="bla bla bla">3</td>
</tr>
<td class="bla bla bla" title="bla bla bla>1.</td>
<td class="bla bla bla"></td>
<td class="bla bla bla">45</td>
<td class="bla bla bla">fnf</td>
<td class="bla bla bla">kfkfk</td>
</tr>
.
.
.
allRows size gives me a correct number of rows.
For some reason, I get cells = null.
I have also tried By.xpath("td") but with no use.

when you loop using this code :
for (WebElement row : allRows) {
ArrayList<WebElement> cells = (ArrayList<WebElement>) row.findElements(By.tagName("td"));
System.out.println("CellCount " + cells.size());
}
You will see that you get output as :
CellCount 0
CellCount 4
CellCount 4
That is because the first row that is picked up by your code is from <thead> section where there are no <td> elements rest it works fine; so you have to make exception for first <tr>
you can do that by changing your allRows element to following:
List<WebElement> allRows = table.findElements(By.xpath("tbody//tr"));

First, find all the rows and then iterate over them:
List<WebElement> allRows = driver.findElements(By.cssSelector("#table-type-1 > tbody > tr"));
for(WebElement row : allRows){
List<WebElement> cells = row.findElements(By.tagName("td"));
System.out.println("Cell count: " + cells.size());//cell count for a row
}

A HTML <table> consists of 3 sections: <thead>, <tbody> and <tfoot>.
Usually you will see only <thead> and <tbody>.
The correct way is to first identify each of these sections and then work your way through their child elements.
// Get the table
WebElement table = a_chromeWebDriver.findElement(By.id("table-type-1"));
// Get the thead in table
WebElement thead = table.findElement(By.tagName("thead"));
// Get the tbody in table
WebElement tbody = table.findElement(By.tagName("tbody"));
// Get all headers in thead
List<WebElement> allHeaders = thead.findElements(By.tagName("th"));
// Get all rows in tbody
List<WebElement> allRows = tbody.findElements(By.tagName("tr"));
// Get all cells for each row in allRows
for(WebElement row : allRows) {
List<WebElement> allCells = row.findElements(By.tagName("td"));
int rowNum = allRows.indexOf(row) + 1;
System.out.println("Row no. " + rowNum + " has " + allCells.size() +" cells.");
}

Related

Stuck with showing data from json apicall visualforce apex

Hi the Im trying to get data from an api, I already deserialized the json,
But when I try to get the data in visualforce just shows me 1 value, and I dont get it, I ve been reading the documentation but still I have errors
Can anyone help me to understand what is wrong?
this is the response of my class
HTTPResponse response = h.send(request);
Map<String,object> results = new Map<String,object>();
List<Object> listResponse = new List<Object>();
Map<String,object> MapeoNombre = new Map<String,object>();
List<String> Nombre = new List<String>();
Integer counter = 0;
Integer num = 0;
Integer i = 1;
// Parse the JSON response
if(response.getStatusCode() == 200) {
results = (Map<String,object>)JSON.deserializeUntyped(response.getBody());
Map<String, Object> body = (Map<String, Object>)results.get('body');
listResponse = (List<Object>) body.get('asegurados');
num = listResponse.size();
System.debug('list:'+listResponse);
} else {
System.debug('The status code returned was not expected: ' + response.getStatusCode() + ' ' + response.getStatus());
}
for (Object asegurado:listResponse ){
if(counter<num){
MapeoNombre =(Map<String, Object>)asegurado;
Nombre.add((String)MapeoNombre.get('nombreAsegurado'));
i++;
}
itemName =(string)MapeoNombre.get('nombreAsegurado');
itemLastName =(string)MapeoNombre.get('apellidoPaterno');
itemSecondLastName =(string)MapeoNombre.get('apellidoMaterno');
itemRamo =(string)MapeoNombre.get('ramo');
itemPoliza =(string)MapeoNombre.get('poliza');
System.debug('nombre'+itemName);
System.debug('apellida paterno'+itemLastName);
System.debug('apellido materno'+itemSecondLastName);
System.debug('poliza'+itemPoliza);
}
and this is my visualforce
<apex:form >
<apex:inputText value="{!ramopoliza}"/>
<apex:pageBlock >
<apex:commandButton reRender="table1" value="Buscar" action="{!busqueda}"/>
</apex:pageBlock>
<apex:pageBlock id="table1">
<div class="painel">
<h1>MANCHA</h1>
<table>
<tr>
<th colspan="1" class="celula_em_branco"></th>
<th colspan="4" class="celula_azul_escuro">MANAGED SERVICES</th>
</tr>
<tr>
<td class="cor_cinza td_column">Nombre</td>
<td class="cor_cinza td_column">Apellido Paterno</td>
<td class="cor_cinza td_column">Apellido materno</td>
<td class="cor_cinza td_column">Ramo</td>
<td class="cor_cinza td_column">Poliza</td>
</tr>
<tr>
<td class="celula_azul_escuro">{!itemName}</td>
<td class="cor_azul">{!itemLastName}</td>
<td class="cor_azul">{!itemSecondLastName}</td>
<td class="cor_azul">{!itemRamo}</td>
<td class="cor_azul">{!itemPoliza}</td>
</tr>
<tr>
<td class="celula_azul_escuro">{!itemName}</td>
<td class="cor_azul">{!itemLastName}</td>
<td class="cor_azul">{!itemSecondLastName}</td>
<td class="cor_azul">{!itemRamo}</td>
<td class="cor_azul">{!miprueba}</td>
</tr>
</table>
</div>
<apex:pageblockTable value="{!Nombre}" var="f">
<apex:column value="{!f}"><apex:facet name="header">Object Names</apex:facet></apex:column>
</apex:pageblockTable>
</apex:form>
and this is the Json sample
"code": 1,
"message": "SUCCESS",
"date": "15/07/2022 23:57:00",
"body": {
"asegurados": [
{
"ramo": "37",
"poliza": "0000003101",
"endosoQueModifica": "000000",
"consecutivo": "00000001",
"iniciovigencia": "01/04/2022",
"finVigencia": "01/04/2023",
"nombreAsegurado": "MARCO ANTONIO",
"apellidoPaterno": "MARQUEZ",
"apellidoMaterno": "SOTELO",
"descripcionRamo": "SALUD INDIVIDUAL",
"dependiente": "01 TITULAR",
"fechaNacimiento": "14/08/1992",
"numCertificado": "00000001",
"numDeIncisoEnElCertificado": "00000001"
},
{
"ramo": "37",
"poliza": "0000003101",
"endosoQueModifica": "100002",
"consecutivo": "00000002",
"iniciovigencia": "20/04/2022",
"finVigencia": "01/04/2023",
"nombreAsegurado": "SAYRA FABIOLA",
"apellidoPaterno": "ORDUNO",
"apellidoMaterno": "ELIZONDO",
"descripcionRamo": "SALUD INDIVIDUAL",
"dependiente": "D DEPENDIENTE",
"fechaNacimiento": "22/10/1966",
"numCertificado": "00000001",
"numDeIncisoEnElCertificado": "00000002"
}
]
}
}
asegurados is a list

how to apply filter on JQuery DataTable each columns? [duplicate]

I'm trying to filter table rows in an intelligent way (as opposed to just tons of code that get the job done eventually) but a rather dry of inspiration.
I have 5 columns in my table. At the top of each there is either a dropdown or a textbox with which the user may filter the table data (basically hide the rows that don't apply)
There are plenty of table filtering plugins for jQuery but none that work quite like this, and thats the complicated part :|
Here is a basic filter example http://jsfiddle.net/urf6P/3/
It uses the jquery selector :contains('some text') and :not(:contains('some text')) to decide if each row should be shown or hidden. This might get you going in a direction.
EDITED to include the HTML and javascript from the jsfiddle:
$(function() {
$('#filter1').change(function() {
$("#table td.col1:contains('" + $(this).val() + "')").parent().show();
$("#table td.col1:not(:contains('" + $(this).val() + "'))").parent().hide();
});
});
Slightly enhancing the accepted solution posted by Jeff Treuting, filtering capability can be extended to make it case insensitive. I take no credit for the original solution or even the enhancement. The idea of enhancement was lifted from a solution posted on a different SO post offered by Highway of Life.
Here it goes:
// Define a custom selector icontains instead of overriding the existing expression contains
// A global js asset file will be a good place to put this code
$.expr[':'].icontains = function(a, i, m) {
return $(a).text().toUpperCase()
.indexOf(m[3].toUpperCase()) >= 0;
};
// Now perform the filtering as suggested by #jeff
$(function() {
$('#filter1').on('keyup', function() { // changed 'change' event to 'keyup'. Add a delay if you prefer
$("#table td.col1:icontains('" + $(this).val() + "')").parent().show(); // Use our new selector icontains
$("#table td.col1:not(:icontains('" + $(this).val() + "'))").parent().hide(); // Use our new selector icontains
});
});
This may not be the best way to do it, and I'm not sure about the performance, but an option would be to tag each column (in each row) with an id starting with a column identifier and then a unique number like a record identifier.
For example, if you had a column Produce Name, and the record ID was 763, I would do something like the following:
​​<table id="table1">
<thead>
<tr>
<th>Artist</th>
<th>Album</th>
<th>Genre</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td id="artist-127">Red Hot Chili Peppers</td>
<td id="album-195">Californication</td>
<td id="genre-1">Rock</td>
<td id="price-195">$8.99</td>
</tr>
<tr>
<td id="artist-59">Santana</td>
<td id="album-198">Santana Live</td>
<td id="genre-1">Rock</td>
<td id="price-198">$8.99</td>
</tr>
<tr>
<td id="artist-120">Pink Floyd</td>
<td id="album-183">Dark Side Of The Moon</td>
<td id="genre-1">Rock</td>
<td id="price-183">$8.99</td>
</tr>
</tbody>
</table>
You could then use jQuery to filter based on the start of the id.
For example, if you wanted to filter by the Artist column:
var regex = /Hot/;
$('#table1').find('tbody').find('[id^=artist]').each(function() {
if (!regex.test(this.innerHTML)) {
this.parentNode.style.backgroundColor = '#ff0000';
}
});
You can filter specific column by just adding children[column number] to JQuery filter. Normally, JQuery looks for the keyword from all the columns in every row. If we wanted to filter only ColumnB on below table, we need to add childern[1] to filter as in the script below. IndexOf value -1 means search couldn't match. Anything above -1 will make the whole row visible.
ColumnA | ColumnB | ColumnC
John Doe 1968
Jane Doe 1975
Mike Nike 1990
$("#myInput").on("change", function () {
var value = $(this).val().toLowerCase();
$("#myTable tbody tr").filter(function () {
$(this).toggle($(this.children[1]).text().toLowerCase().indexOf(value) > -1)
});
});
step:1 write the following in .html file
<input type="text" id="myInput" onkeyup="myFunction()" placeholder="Search for names..">
<table id="myTable">
<tr class="header">
<th style="width:60%;">Name</th>
<th style="width:40%;">Country</th>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Germany</td>
</tr>
<tr>
<td>Berglunds snabbkop</td>
<td>Sweden</td>
</tr>
<tr>
<td>Island Trading</td>
<td>UK</td>
</tr>
<tr>
<td>Koniglich Essen</td>
<td>Germany</td>
</tr>
</table>
step:2 write the following in .js file
function myFunction() {
// Declare variables
var input, filter, table, tr, td, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
table = document.getElementById("myTable");
tr = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the search query
for (i = 0; i < tr.length; i++) {
td = tr[i].getElementsByTagName("td")[0];
if (td) {
if (td.innerHTML.toUpperCase().indexOf(filter) > -1) {
tr[i].style.display = "";
} else {
tr[i].style.display = "none";
}
}
}
}

Getting th element in table of specific index in protractor

<table>
<thead>
<th>name</th>
<th>place</th>
<th>area</th>
</thead>
<tbody>
<tr><td>name</td><td>jjhds</td><td>dfdsf</td></tr>
<tr><td>name</td><td>jjhds</td><td>dfdsf</td></tr>
<tr><td>name</td><td>jjhds</td><td>dfdsf</td></tr>
<tr><td>name</td><td>jjhds</td><td>dfdsf</td></tr>
<tr><td>name</td><td>jjhds</td><td>dfdsf</td></tr>
</tbody>
</table>
I have above table. I need to navigate from td in tbody and get its heading in thead****th through protractor. Please can anyone help?
One option would be to get the desired header by an index of a column in a row, sample:
var table = $('table'); // TODO: too general of a locator, improve
var headers = table.$$('th');
table.$$('tr').each(function (row) {
row.$$('td').each(function (cell, index) {
cell.getText().then(function (cellText) {
headers.get(index).getText().then(function (headerText) {
console.log("Header: " + headerText + ", Cell Value: " + cellText);
});
});
});
});
Using .each() here just for demonstration purposes.

How to get all direct(immediate) rows from WebElement Table

From the below table I need immediate row elements using Xpath or "css-selector" or Selenium API :- element.findelements. Please help.
<table id ="Main">
<tbody>
<tr id="row_1">
<tr id="row_1_1">
<tr id="row_1_1_1">
</tr>
</tr>
</tr>
<tr id="row_2">
</tr>
<tr id="row_3">
<tr id="row_3_1">
</tr>
</tr>
</tbody>
</table>
Expected Output:-
[<tr id="row_1">,<tr id="row_2">,<tr id="row_3">]
Imp Note:- I am looking for a generic solution. Sometimes tbody wont be present in the table. I am having Table WebElement with me.
You can use xpath union operator (|) to combine multiple xpath expressions, f.e one to handle the case when tbody exists, and another for the case when tbody doesn't exist :
//table[#id='Main']/tbody/tr | //table[#id='Main']/tr
Use below locator
By.cssSelector("table#Main > tbody > tr")
Or
By.xpath("//table[#id='Main']/tbody/tr")
List<WebElement> allRows = driver.findElements(By.cssSelector("table#Main > tbody > tr"));
for(WebElement ele : allRows) {
//do your operation with that row
//ele.getText();
}

how to get the class name through selenium

<table >
<tr class="odd First"><td>1one Cell</td><td>2one Cell</td><td>3one Cell</td><td>4one Cell</td> </tr>
<tr class="even Second"><td>Two Cell</td><td>2Two Cell</td><td>3Two Cell</td><td>4Two Cell</td></tr>
<tr class="odd Thrid"><td>1Three Cell</td><td>2Three Cell</td><td>3Three Cell</td><td>4Three Cell</td></tr>
<tr class="even Fourth"><td>1Five Cell</td><td>2Five Cell</td><td>3Five Cell</td><td>4Five Cell</td></tr>
</table>
How can i get the class names of the tr. Please suggest me.
To get the class names of all the tags using java.
List<WebElement> list = driver.findElements(By.tagName("tr"));
for(WebElement ele:list){
String className = ele.getAttribute("class");
System.out.println("Class name = "+className);
}
This will print all the class names to the console for all the tags on the web page.
String className = selenium.getAttribute("//html/body/table/tbody/tr[1]/#class");
May be this code might get you the value of the first tag's class name. Let me know if this works.
List0 = []
List1 = driver.find_elements(By.XPATH, '/table/tr')
for element in List1:
name = element.get_attribute('class')
List0.append(name)
print(List0)