Webdriver getText method with truncate using Java - java

Html Code
<table id="tblRenewalsFiled" class="StatusList" width="100%" cellspacing="0" cellpadding="0" border="0">
<tbody data-bind="foreach: RenewalFilterModels">
<tr>
<td>
<a id="aFilterMenu_NotAudited" class="aFilter"
data-bind="click: $parent.ShowFilter, attr:{'id':'aFilterMenu_' + StatusName}" href="#">
Not Audited
<span class="count">13</span>
</a>
</td>
</tr>
</tbody>
</table>
from the above, when I use the getText, method it will return "Not Audited 13"
String filterValue = driver.findElement(By.id("aFilterMenu_NotAudited").getText();
my expectation was only for Not Audited, provide an solution or suggestion to truncate the span class count i.e "13"

So all I can to advice is to take cssSelector "a.aFilter, span", it will return an array of two elements [ 'Not Audited 13', '13' ]
String[] value = driver.findElement(By.id("aFilterMenu_NotAudited").getText();
then you are truncating the second element from the end of the first one:
String myText = value[0].substring(0, value[0].length() - value[1].length());
Looks like a bit tricky.
Another way is using xpath:
//a[#class='aFilter'][not(self::span)]/text()

Related

How to get value inside <td> which is inside tr[2] by finding a text whose <th> is inside tr[1] using java

I am new to selenium and I need to get the value £1000 which is inside
td class='ng-ngclass' /td
and i need to find that by finding text 'Wrapper1' from
th class="ng-ngclass" colspan="3" - Wrapper1 - /th
I should pass the text 'Wrapper1' in %s in the below constant
I've tried the below one
private static final String WRAPPER_VALUE = "//th[#class='ng-ngclass'and contains(text(), %s)] and //td[#class='ng-ngclass']" in FirePath but it is returning me 1 number: NaN in firefox console.. What does that really mean?
Please help me. Any help will be appreciated.
<div id="summaryEncash" class="body scroll-body" ng-class=" {clsOnlyAdPlan: hasOverview === false}">
<!-- ngRepeat: asset in assetTypes -->
<table class="data-stripe ng-scope" ng-repeat="asset in assetTypes" analytics="homePortfolioTap" ng-click="showAssetDetail(0)" cellspacing="0" cellpadding="0">
<tbody>
<tr ng-show="isCurrentValue">
<th class="ng-ngclass" colspan="3">Wrapper1</th>
</tr>
<tr class="summary-value" ng-show="isCurrentValue">
<td class="ng-ngclass">£1000</td>
<td/>
<td class="arrow">
<i class="next next-arrow"/>
</td>
</tr>
The Xpath expression //td[#class='ng-ngclass'] returns the td element with its text node.
The Xpath expression //td[#class='ng-ngclass']/text() should return the text value of td element. So the string £1000. Then you have to parse it to get a number.

How to make contains() method dynamic in selenium

I am tring to pass the value from excel to xpath but I am getting noSuchElementFoundException.
This is the code :
public String accountBalance(String accountNameToFind)
{
String accountBalance = null;
accountBalance = driver.findElement(By.xpath("//*[contains(text(),'" + accountNameToFind + "')]/following-sibling::td")).getText();
return accountBalance;
}
HTML:
<tr>
<th scope="row" class="">
SDRSP
<sup>2</sup> - <span class="td-copy-nowrap">1253 3292AUS</span>
<strong>
<a href="servlet/ca.tdbank.banking.servlet.SiteTransferOutServlet?dest=BROKER" class="td-link-standalone td-link-standalone-secondary">
<span class="td-copy-nowrap">
WebBroker
<span class="td-link-icon">›</span>
</span>
</a>
</strong>
</th>
<td class="td-copy-align-right">
$10,000.00
</td>
<td class="td-copy-align-centre">
</td>
</tr>
If your element located inside frame, you need to switch to it first and then handle element:
driver.switchTo().frame("frame_ID");
accountBalance=driver.findElement(By.xpath("//*[contains(text(),'"+accountNameToFind+"')]/following-sibling::td")).getText();
...some other actions...
driver.switchTo().defaultContent();
If your frame has no id attribute you can try to use another attributes, e.g. class name:
driver.switchTo().frame(driver.findElement(By.cssSelector("frame.frameClassName")));
Your function should be simplified to the below.
public String accountBalance(String accountNameToFind)
{
return driver.findElement(By.xpath("//th[contains(text(),'" + accountNameToFind + "')]/following-sibling::td")).getText();
}
I replaced * with th in the XPath because I'm assuming that the th is going to be the only element that you want to use. The accountName may exist elsewhere on the page and be causing issues.
If this is in a frame/iframe, you will need to switch to the frame first as in #Andersson's answer.
This may be a case where this portion of the page is dynamic so you may have to wait for the element to be visible before trying to scrape the data. See WebDriverWait with ExpectedConditions.elementToBeVisible().

Handling multiple tables using selenium webdriver

I am checking the folder hierarchy on a webpage, depending on the type of user. User1 has a set of permissions which enable him to see the folder structure like this :
Main Folder
- First Child
-First Grandchild
-Second Grandchild
- Second Child
- Third Child
Each branch of the tree is a table consisting of 1 row. But the number of columns varies depending on the generation.
The "Main Folder" parent has only 1 column. The cell content is the string "Main Folder".
The children branches have 2 columns, the first cell containing blank space, and the next cell containing the name of the branch ("First Child", "Second Child").
The grandchildren branches have 3 columns, the first and second cell containing blank space, and the the third cell containing the name of the branch (" First Grandchild", "Second Grandchild").
HTML code :
<div id = 0>
<div id = 1>
<table id = 1>
<tbody>
<tr>
<td id="content1"
<a id="label1"
<span id="treeNode1"
Main Folder
</span>
</a>
</td>
</tr>
</tbody>
</table>
<div id = 2>
<table id = 2>
<tbody>
<tr>
<td>
<td id="content2"
<a id="label2"
<span id="treeNode2"
First Child
</span>
</a>
</td>
</td>
</tr>
</tbody>
</table>
<div id = 5>
<table id = 5>
<tbody>
<tr>
<td>
<td>
<td id="content5"
<a id="label5"
<span id="treeNode5"
First GrandChild
</span>
</a>
</td>
</td>
</td>
</tr>
</tbody>
</table>
</div>
<div id = 6>
<table id = 6>
<tbody>
<tr>
<td>
<td>
<td id="content6"
<a id="label6"
<span id="treeNode6"
Second GrandChild
</span>
</a>
</td>
</td>
</td>
</tr>
</tbody>
</table>
</div>
</div> /* End of division 2 */
<div id = 3>
<table id = 3>
<tbody>
<tr>
<td>
<td id="content3"
<a id="label3"
<span id="treeNode3"
Second Child
</span>
</a>
</td>
</td>
</tr>
</tbody>
</table>
</div>
<div id = 4>
<table id = 4>
<tbody>
<tr>
<td>
<td id="content4"
<a id="label4"
<span id="treeNode4"
Third Child
</span>
</a>
</td>
</td>
</tr>
</tbody>
</table>
</div>
</div> /*End of division 1 */
</div> /* End of division 0 */
User2 has a different set of permissions, which enable him to see the folder structure like this :
Main Folder
- First Child
-First Grandchild
- Second Child
- Third Child
The corresponding table is absent in the html code for this user.
My test case is to check User2 doesn't have access to the second grandchild. This means I need to ensure that particular table doesn't exist on the webpage.
How can I check this in selenium ? I am using JUnit for my test cases. I want to do an "assert" to ensure the second grandchild is not present.
You'll want to check to see if the element is not present or not visible. Calling isElementVisible() inside an assert false should do the trick. Just get the By locator of the elements you want to check.
private boolean isElementVisible(By by)
{
try
{
return driver.findElement(by).isDisplayed();
}
catch(NoSuchElementException e)
{
return false;
}
}

Detect innermost web element in (nested) in selenium

I am looking for getting the inner most web element in a page, when there are similar nested Webelements in a page.
Consider the example below:
<body>
<table id="level1">
<tr>
<td>
<table id="level2">
<tr>
<td>
<table id="level3">
<tr>
<td>
<p>Test</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
<table id="level1_table2">
<tr>
<td>
<table id="level2_table2">
<tr>
<td></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
So when I do a search on the page by Driver.findElements by tag "table" and which have some text - "Test",
I will get 5 WebElements in total, namely - "level1", "level3" , "level1_table2" , "level2_table2"
What I want to achieve is to have a list of innermost(nested) elements which satisfy my search criteria .
So the List I should get should only have 2 WebElements namely - "level3" and "level2_table2".
I am looking something probably on the lines of recursion. Can somebody help me out.
You don't need recursion - everything you need is the proper XPath expression:
driver.findElements(By.xpath("table[not(.//table)]"))
I would use this strategy:
Search WebElements containing text Test
For each WebElement search for the first parent which match tag name is table
Here is in Java:
List<WebElement> elementsWithTest = driver.findElements(By.xpath("//*[contains(text(),'Test')]"));
List<WebElement> result = new ArrayList<>();
for(WebElement element : elementsWithTest) {
WebElement parent = element.findElement(By.xpath(".."));
while (! "table".equals(parent.getTagName())) {
parent = parent.findElement(By.xpath(".."));
}
if ("table".equals(parent.getTagName())) {
result.add(parent);
}
}
System.out.println(result);
Hope that helps.

Check box Click Method issue ( similar xpath) - WebDriver using java

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

Categories