I've tried searching for this one, and tried multiple solutions that I found on here. But so far nothing is working.
The table I'm trying to get data from is being created after entering something into the page. The site then pulls data from what I entered and creates a table. I've had issues with just getting the driver to wait for the table to be visible, it can't find the element.
Here's some html.
<table id="products">
<thead>
<tbody>
<tr class="template subheading-template subheading draggable removeable">
<tr class="template spec-template draggable product removeable odd">
<tr class="components hide modify">
<tr class="draggable product removeable even" data-id="G38180">
<td class="drag"/>
<td>
<td class="cell-gpn">G38180</td>
<td class="cell-rpn">0729151158PROD2</td>
<td class="cell-1 editable">
<td class="cell-2 editable">
<td class="cell-3 editable">
<td class="cell-4 editable">
The cells I want data from have the class "cell-gpn" and "cell-rpn".
Here's some of the code I've tried.
public String getTableData(WebElement table,String rowNumber, String cellNumber){
String text = "";
WebElement row = table.findElement(By.xpath("./tr[" + rowNumber + "]"));
WebElement key = row.findElement(By.xpath("./td[" + cellNumber + "]"));
text = key.getText();
return text;
}
Where table is
#FindBy(xpath = "//table[#id='products']")
public WebElement relatedProductsTableRows;
Related
1) I want to capture quote id.But instead, it will capture review on the console.
2) I am using selenium web driver with java.
3) Just want the quote id to printed on the console all the details are mentioned below.
I want to capture quote id from a webpage using selenium web driver.Below are my dom structure and the code that I have used. But instead, it is printing the review text is part of XPath.
Dom structure of my page:
<tbody>
<tr>
<tr id="pricerow" valign="top">
<td nowrap="nowrap">
3661017
<br/>
<a class="selectMenuHome" style="color: gray; text-transform: none; text-decoration: underline;cursor:hand;" alt="TestSITA" title="TestSITA">Review</a>
</td>
<td nowrap="nowrap">UNITED KINGDOM</td>
<td>London</td>
<td> 1 Ropemaker Street, London, United Kingdom </td>
<td nowrap="nowrap">3456789</td>
<td nowrap="nowrap"/>
<td nowrap="nowrap">2 Mbps</td>
<td nowrap="nowrap">ME</td>
<td nowrap="nowrap">Business VPN Corporate</td>
<td nowrap="nowrap">211</td>
Xpath that have used: (.//*[#id='pricerow']/td[1])[1]
Quote capture code:
public static void QuoteCapture() throws Exception{
logmessage = ExcelUtils.getCellData(Constant.testcaserownum,
Constant.TestStepID)
+ "; "
+ ExcelUtils.getCellData(Constant.testcaserownum,
Constant.TeststepDescription)
+ "; Action: Capture and stored value";
Log.info(logmessage);
String[] fetchfrompage = null;
ActionElement = FindElement();
if (ExcelUtils.getCellData(Constant.testcaserownum, Constant.Data1)
.isEmpty()) {
fetchfrompage = ActionElement.getText().split("\n");
ValueCaptured.add(fetchfrompage[0]);
// ValueCaptureindex=ValueCaptureindex+1;
int size = ValueCaptured.size();
size = size - 1;
logmessage = ValueCaptured.get(size)
+ "; Value has been stored in index: " + size;
}
Log.info(logmessage);
}
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);
I am trying to click the CSS below
html body.FormBackground form#LookupForm div#Panel1 table tbody tr td div#GridContainerDiv div table#DataGrid tbody tr.GridSelectedRow td.GridRow
So far I have tried
#FindBy(css = "#DataGrid\\tbody\\tr.GridSelectedRow > td.GridRow")
and
#FindBy(css = "#DataGrid tbody tr.GridSelectedRow > td.GridRow")
But neither of the above attempts seem to work. HTML is below.
<tbody>
<tr ondblclick="$HRnet('DataGrid').dblClick(); " gender_id="f6611f8a-8e80-41e6-a14c-fa8e25be3065" class="GridUnSelectedRow">
<td class="GridRow">Female</td>
</tr>
<tr ondblclick="$HRnet('DataGrid').dblClick(); " gender_id="3ef09fb8-4d5d-43d2-abc0-2506616ef83e" class="GridSelectedRow">
<td class="GridRow">Male</td>
</tr>
<tr nofocus="true">
<td> </td>
</tr>
</tbody>
Based on what you've shared it looks like this should work but it will return multiple rows so you'll need to decide which one you want to click
#FindBy(css = "#DataGrid td.GridRow")
two different Div's inside the Div have an check box, so i want to click the checkbox (i.e inside the "divPatPortfolioStatusCount"), both checkbox xpath are similar
(i.e By.xpath("//input[#accesskey='2']")
Html Code
<div id="divCreatePortfolio" class="wrapper">
<table class="adminlistfilter" width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr data-bind="if: RowCounts>0, attr: {PortfolioId: Id, DescName:Name}" portfolioid="2" descname="Client-Default">
<td style="width: 5%;">
<input type="checkbox" data-bind="attr: { accesskey: Id }" accesskey="2">
</td>
</tr>
</tbody>
</table>
</div>
<div id="divPatPortfolioStatusCount" class="wrapper">
<table class="adminlistfilter" width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr data-bind="if: RowCounts>0, attr: {StatusId: Id, DescName:Name}" statusid="2" descname="Abandoned">
<td style="width: 5%;">
<input type="checkbox" data-bind="attr: { accesskey: Id }" accesskey="2">
</td>
</tr>
</tbody>
</table>
</div>
</div>
my Java code
WebElement statusDiv= driver.findElement(By.id("divPatPortfolioStatusCount"));
WebElement checkBox = statusDiv.findElement(By.xpath("//input[#accesskey='2']"));
checkBox.click();
while executing under the "divCreatePortfolio" checkbox only checked not for "divPatPortfolioStatusCount" let me know the problem with my xpath
You need click on those 2 different check box separately as below right?
//To check Status checkbox
driver.findElement(By.xpath("//div[#id='divCreatePortfolio']//input")).click();
//To check Status count checkbox
driver.findElement(By.xpath("//div[#id='divPatPortfolioStatusCount']//input")).click();
I would suggest you to use css and nth-child() function and control child index from test
body>div:nth-child(1) input
body>div:nth-child(2) input
Changing the number of nth-child(1) from 1 to 2 will find consecutive check boxes
update the xpath in my code
WebElement statusTable = driver.findElement(By
.xpath("//*[#id='divPatPortfolioStatusCount']/table/tbody"));
List<WebElement> rows = statusTable.findElements(By.tagName("tr"));
for (int i = 0; i < rows.size(); i++) {
WebElement checkBoxSts = driver
.findElement(By
.xpath("//*[#id='divPatPortfolioStatusCount']/table/tbody/tr["
+ i + "]"));
String statusAccessKey = checkBoxSts.getAttribute("statusid");
if (statusAccessKey.equals(portfolioId)) {
WebElement checkbox = driver
.findElement(By
.xpath("//*[#id='divPatPortfolioStatusCount']/table/tbody/tr["
+ i + "]/td[1]/input"));
checkbox.click();
break;
}
}
collect the statusid from database with respective of status and pass the statusid in this method with parameter, and proceed
you can do it as :
List<WebElements> lst = driver.findElements(By.xpath("//input[#accesskey='2']"));
for (WebElement web : lst)
if(!web.isSelected())
web.click();
And if you want to select input based on div id u can use:
//div[#id='divPatPortfolioStatusCount']//input
I'm automating a task using Java and Selenium.
I want to set a checkbox (which is in the first column of a table) based on whether the value in the second column matches my input value. For example, in the following code snippet, the value "Magnus" matches my input value so I want to set the checkbox associated with it.
<table class="cuesTableBg" width="100%" cellspacing="0" border="0" summary="Find List Table Result">
<tbody>
<tr class="cuesTableBg">
<tr class="cuesTableRowEven">
<tr class="cuesTableRowOdd">
<td align="center">
<input class="content-nogroove" type="checkbox" name="result[1].chked" value="true">
<input type="hidden" value="1c62dd7a-097a-d318-df13-75de31f54cb9" name="result[1].col[0].stringVal">
<input type="hidden" value="Magnus" name="result[1].col[1].stringVal">
</td>
<td align="left">
<a class="cuesTextLink" href="userEdit.do?key=1c62dd7a-097a-d318-df13-75de31f54cb9">Magnus</a>
</td>
<td align="left"></td>
<td align="left">Carlsen</td>
<td align="left"></td>
</tr>
<tr class="cuesTableRowEven">
</tbody>
</table>
But I'm unable to do it. In the above case, the following two lines serve the purpose (as my input value matches with that in the second row):
WebElement checkbox = driver.findElement(By.xpath("//input[#type = 'checkbox' and #name = 'result[1].chked']"));
checkbox.click();
But it can't be used as the required value might not always be in the second row.
I tried following code block but to no avail:
List<WebElement> rows = driver.findElements(By.xpath("//table[#summary = 'Find List Table Result']//tr"));
for (WebElement row : rows) {
WebElement userID = row.findElement(By.xpath(".//td[1]"));
if(userID.getText() == "Magnus") {
WebElement checkbox = row.findElement(By.xpath(".//input[#type = 'checkbox']"));
checkbox.click();
break;
}
}
For what it's worth, XPath of the text in the second column:
/html/body[#id='mainbody']/table/tbody/tr/td/div[#id='contentautoscroll']/form/table[2]/tbody/tr[3]/td[2]/a
I don't know about CSS Selectors. Will it help here?
If you know the input value already you just use below xpath to select respected checkbox
"//a[text(),'Magnus']/parent::td/preceding-sibling::td/input[#type='checkbox']"
Update:
"//a[text()='Magnus']/parent::td/preceding-sibling::td/input[#type='checkbox']"
While comparing two strings equals should be used instead of ==
Replace
if(userID.getText() == "Magnus")
with
String check1 = userID.getText();
if(check1.equals("Magnus")
Seems like it was a silly mistake on my part. The following code snippet, a fairly straightforward one, worked.
List<WebElement> rows = driver.findElements(By.xpath("//table[#class='cuesTableBg']//tr"));
for (WebElement row : rows) {
WebElement secondColumn = row.findElement(By.xpath(".//td[2]"));
if(secondColumn.getText().equals("Magnus")) {
WebElement checkbox = row.findElement(By.xpath(".//td[1]/input"));
checkbox.click();
break;
}
}