Pagination in webDriver displays Stale Element Reference Exception - java

Environment : Eclipse, Chrome, Java
I am dealing with test case for pagination in the application. I have tried with some code, but it moves only upto 2nd page.
Code :
List<WebElement> allpages = driver.findElements(By.xpath("//div[#class='pagination']//a"));
System.out.println(allpages.size());
if(allpages.size()>0)
{
System.out.println("Pagination exists");
for(int i=0; i<allpages.size(); i++)
{
Thread.sleep(3000);
allpages.get(i).click();
driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
//System.out.println(i);
}
}
else
{
System.out.println("Pagination doesn't exists");
}
}
Size displayed is 12. The issue is it moves upto 2nd page only and then displays error of StaleElementReference
Here's the HTML Code for the same pagination.
HTML Code :
<div id="page-navigation" class="pull-right">
<div id="303b171e-5a26-e456" class="flex-view">
<div class="pagination">
<ul>
<li class="">
«
</li>
<li class="" data-value="0">
1
</li>
<li class="" data-value="1">
2
</li>
<li class="active" data-value="2">
3
</li>
.....

When the new page is loaded after clicking one of the pagination links, the allpages WebElements are no longer valid and need to be found again. You will have to put another call to allpages = driver.findElements(By.xpath("//div[#class='pagination']//a")); in your for loop so that you can get new references for each new page.

Related

I want to extract all <li> element text that are under <ul>

I need to click on all elements BASIC, TRACKS, ...
My idea is to extract all elements in list then using list count and loop, I'll click on each and every element.
Need to check that each and every element is working even if new element is added I don't want to check code.
<div class="headerarea" style="" xpath="1">
<h2>
<span id="ctl00_ctl00_phDesktop_lblModuleTitle">Abstract Setup</span>
</h2>
<ul>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl01_btnModuleNavigation" class="headerarea_active" href="https://staging.m-anage.com/Modules/Abstract/Setup/basics.aspx">Basic</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl02_btnModuleNavigation" href="https://staging.m-anage.com/testselenium/en-US/Abstract/AbstractSetup/Tracks">Tracks</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl03_btnModuleNavigation" href="https://staging.m-anage.com/Modules/Abstract/Setup/steps.aspx">WIZARD</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl04_btnModuleNavigation" href="https://staging.m-anage.com/Modules/Abstract/Setup/keywords.aspx">KEYWORDS</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl05_btnModuleNavigation" href="https://staging.m-anage.com/Modules/Abstract/Setup/categories.aspx">CATEGORIES</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl06_btnModuleNavigation" href="https://staging.m-anage.com/Modules/Abstract/Setup/conditions.aspx">CONDITIONS</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl07_btnModuleNavigation" href="https://staging.m-anage.com/Modules/Abstract/Setup/interests.aspx">Interests</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl08_btnModuleNavigation" href="https://staging.m-anage.com/Modules/Abstract/Setup/templates.aspx">Templates</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl09_btnModuleNavigation" href="https://staging.m-anage.com/testselenium/en-US/Abstract/AbstractSetup/Index">Submission fee</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl10_btnModuleNavigation" href="https://staging.m-anage.com/testselenium/en-US/Mail/MailServerSetup/Index?pModuleType=Abstract" style="">SMTP Setup</a></li>
<li>
<a id="ctl00_ctl00_phDesktop_rModuleNavigation_ctl11_btnModuleNavigation" href="https://staging.m-anage.com/testselenium/en-US/Abstract/AbstractSetup/Coauthor">Co-author</a></li>
</ul>
</div>
I tried travelling to child path but no success
Here is the java code that I tried.
List<WebElement> tags =
driver.findElements(By.xpath("//div[#class='headerarea']/ul/li"));
for(int i=0;i<tags.size();i++) {
while(???) {
//driver.findElement(By.xpath("//div[#class='headerarea']/ul/li")).click();
}
}
Try below code :
List<WebElement> links = driver.findElements(By.tagName("li"));
for (int i = 1; i < links.size(); i++)
{
System.out.println(links.get(i).getText());
}
You can also use WebDriverWait if you are facing synchronization issue.
WebDriverWait wait = new WebDriverWait(driver, 10);
List<WebElement> links = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.tagName(li)));
for (int i = 1; i < links.size(); i++)
{
System.out.println(links.get(i).getText());
}
List<WebElement> tags = driver.findElements(By.cssSelector(".headerarea ul>li"));
for(WebElement e : tags) {
e.click();
}

How to get the text attribute of a input element? - webdriver

<ul class="list-group opened-list d-none" xpath="1">
<li class="list-group-item col-12" xpath="1">My team</li>
<li class="list-group-item col-12" xpath="1">My name</li>
<li class="list-group-item col-12" xpath="1">My film</li>
<li class="list-group-item col-12" xpath="1">My football teammate</li>
</ul>
Dropdown list without select tag
To get all li elements use .list-group.opened-list .list-group-item css selector.
Code below wait visibility of li elements and then print text for each:
WebDriverWait wait = new WebDriverWait(driver, 10);
List<WebElement> options = wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.cssSelector(".list-group.opened-list .list-group-item")));
options.forEach(element -> System.out.println(element.getText()));
If you want to select one of the element by text, check example here.

why am I receiving stale element reference on test method?

I am currently working on an automation framework using java, selenium, selenium-grid, pageObject with pageFactory.
I am trying to create a method for testing the following html code:
<section class="footer-links">
<div class="footer-layout">
<ul>
<li class="title">Header</li>
<li>text</li>
<li>text</li>
<li>text</li>
<li><a href="/games/download/" >text</a></li>
<li><a href="/games/mobile/" >text</a></li>
<li><a href="/events/" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/publishers/" >text</a></li>
<li><a href="/smth/" target="_blank" >text</a></li>
<li><a href="/promo/press/" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/support/" >text</a></li>
<li><a href="/support/payment-inquiries/" class="loginModalShow" rel="nofollow" >text</a></li>
<li><a href="/support/general-inquiries/" >text</a></li>
<li><a href="/support/game-inquiries/" class="loginModalShow" rel="nofollow" >text</a></li>
</ul>
<ul>
<li class="title">Header</li>
<li><a href="/blog/" >text</a></li>
<li><a href="/search/" rel="nofollow" >text</a></li>
<li><a href="/directory/pc-games/" >text</a></li>
</ul>
</div>
The code above represents a footer containing 4 lists with some links.
What I am trying to do with the following method is to iterate once through the 4 lists and again inside each list clicking the links and verifying the url to which they redirect against their href attribute value.
#FindBy(css = ".footer-links .footer-layout ul")
public List<WebElement> footerLinksLists;
public void checkFooterLinks(){
if (footerLinksLists.size()==4){
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(driver.getCurrentUrl().contains(href)){
log.info("Link " + href +" is ok");
}
driver.navigate().back();
}
}
}else{
log.info("the footer does not contain 4 link lists");
}
}
After starting my test it breaks after entering the for loop with the following error
org.openqa.selenium.StaleElementReferenceException: The element reference of <li> is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed
In my test class I have the following code for initializing pageobject containing the method:
WebDriver driver = driverFactory.getDriver();
WebDriverWait wait = driverFactory.getWait(driver);
homepagePageObject homePage = new homepagePageObject(driver, wait);
PageFactory.initElements(driver,homePage);
homePage.createAccount();
homePage.checkVerifyAccountRibbon();
homePage.signOut();
homePage.Login();
homePage.checkFooterLinks();
Initially I thought it had something to do with waiting for each element but I am receiving the same error after adding the waits/expectedConditions.
Can somebody explain what am I doing wrong and what would be the best solution in this case?
Because page get refresh and List element lost its value.
You have to manage it By reassign links value.
public void checkFooterLinks(){
if (footerLinksLists.size()==4){
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(driver.getCurrentUrl().contains(href)){
log.info("Link " + href +" is ok");
}
driver.navigate().back();
}
links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"))));
}
}else{
log.info("the footer does not contain 4 link lists");
}
}
This method doesn't do what you want it to do.
First, it only goes through this loop if the number of footerlinks is 4.
If the number of links is changed, or there is a bug that causes it to be 3, the whole method is skipped and you just get a log statement to the fact.
Since there are no assertions, and the method does not return anything, this method will pass every time it is run.
Second, if the link does not contain the expected href, the if-statement won't execute. All that means is that you won't have the OK statement in the logs.
The method will still execute and succeed.
I would suggest to include some assertions with this test. Either as part of each iteration. So something like this:
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
**assertTrue("The expected URL did not match",driver.getCurrentUrl().contains(href));**
driver.navigate().back();
}
or as a return from the method itself
public boolean checkFooterLinks(){
if (!footerLinksLists.size()==4){
return false;
}
for(int i=0; i<footerLinksLists.size(); i++){
List<WebElement> links = wait.until(ExpectedConditions.visibilityOfAllElements(footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)")))); // footerLinksLists.get(i).findElements(By.cssSelector("li:not(:first-child)"));
for (int j=0; j<links.size(); j++) {
WebElement link = wait.until(ExpectedConditions.elementToBeClickable(links.get(j).findElement(By.cssSelector("a"))));
String href = link.getAttribute("href");
link.click();
if(!driver.getCurrentUrl().contains(href)){
return false;
}
driver.navigate().back();
}
}
return true;
}
and then let the test verify the links are ok with
assertTrue("something is not right with the footer links",checkFooterLinks())
What this gives you is that if the number of the links are no 4, or the link opened up does not match the expected, the test will fail.
That said, I can see the value of checking the links and that they contain an expected href value, but I'm not sure what value checking the actual url will give you.
If the href is corrupt, and points to www.google.com, the test will pass as the two values match. Just food for thought.

How do I read the element from a dropdown menu of a html?

I am parsing the following html by Selenium FirefoxDriver -
<div id="primaryNav" style='background: url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/primaryNavBackground._V161555288_.gif") repeat-x bottom;'>
<div id="menuh">
<ul>
<li style="visibility:hidden;
height:24px"/>
<li style='background:url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/tab-unslected-right._V161557413_.gif") no-repeat right top;'>
▼</span>
<div class="parent">
<div class="dropdownlinks">
<div class="subitem">Product Links</div><div class="subitem">Banner Links</div><div class="subitem">Link to Any Page</div><div class="subitem">Link Checker</div>
</div>
</div>
</li>
<li style='background:url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/tab-unslected-right._V161557413_.gif") no-repeat right top;'>
<a href="http://widgets.amazon.in/?_encoding=UTF8&store=httpswwwvanta-21&tag=httpswwwvanta-21" style='float:left;background:url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/tab-unslected-left._V161554471_.gif") no-repeat left top;'>Widgets</a>
</li>
<li style='background:url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/tab-unslected-right._V161557413_.gif") no-repeat right top;'>
<a href="/gp/advertising/api/detail/main.html" style='float:left;background:url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/tab-unslected-left._V161554471_.gif") no-repeat left top;'>Product Advertising API</a>
</li>
<li style='background:url("https://images-na.ssl-images-amazon.com/images/G/31/associates/network/08-ui-elements/tab-unslected-right._V161557413_.gif") no-repeat right top;'>
▼</span>
<div class="parent"><div class="dropdownlinks">
<div class="subitem"><a href="/gp/associates/network/reports/report.html?ie=UTF8&reportType=earningsReport" >Earnings Report</a>
</div><div class="subitem"><a href="/gp/associates/network/reports/report.html?ie=UTF8&reportType=ordersReport" >Orders Report</a>
</div><div class="subitem"><a href="/gp/associates/network/reports/report.html?ie=UTF8&reportType=linkTypeReport" >Link-Type Report</a>
</div><div class="subitem"><a href="/gp/associates/network/reports/report.html?ie=UTF8&reportType=trendsReport" >Daily Trends</a>
</div><div class="subitem"><a href="/gp/associates/network/reports/report.html?ie=UTF8&reportType=tagsReport" >Tracking ID Summary Report</a>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
I am trying to select the "Earnings Report" from the dropdown menu.
I tried like this --
dropDownButton: WebElement = driver.findElement(By.xpath(".//a[#href='https://affiliate-program.amazon.in/gp/associates/network/reports/report.html?ie=UTF8&reportType=earningsReport']"))
dropDownButton.click()
I also tried like this --
val dropDownButton = driver.findElement(By.linkText("Earnings Report"))
dropDownButton.click()
In both the cases, The code runs only when I hover my mouse over the dropdown menu. No manual click is required.
I also tried the following code which I am not sure if correct -
import scala.collection.JavaConversions._
def selectValueFromDropdown( value: String) = {
var options = driver.findElements(By.id("menuh"));
for(option <- options) {
if (value.equals(option.getText())) {
option.click()
}
}
}
selectValueFromDropdown("Earnings Report")
I am kinda lost here. Please suggest a solution in either Java or Scala.
EDIT: I get to this page after log-in from the main page. Can that be a problem?
Please try this:
First select the drop down and then select by value or Index-
Select drpdown = new Select(driver.findElement(By.xpath("Locator of the dropdown"));
drpdown.SelectByValue("Earning Report");
If "Earning Report" is a visible Text then-
drpdown.selectByVisibleText("Earning Report");
As you mentioned that you have to hover your mouse over the dropdown menu for it to work. Your menu also has sub-menus. So, before clicking the link you need to use the "perform" method of "Actions". In this manner it allows Selenium to spot a particular sub-menu while holding the menu. The code for that is:
val menuElement = driver.findElement(By.id("menuh"))
/* If the css selector used below does not match the element that
* fires the hover action then check which element fires it and update
* the selector */
val subMenuElement = driver.findElement(By.cssSelector("#menuh li:nth-child(5)"))
val earningsReportElement = driver.findElement(By.linkText("Earnings Report"))
val action = new Actions(driver)
action.moveToElement(menuElement).perform()
action.moveToElement(subMenuElement).perform()
action.moveToElement(earningsReportElement)
action.click()
action.perform()
try this-
driver.findElement(
By.xpath("//a[contains(#href,'earningsReport')]"))
.click();
The solution given by #Dagojvg worked after re-arranging the expressions.
import org.openqa.selenium.interactions.Actions
val action = new Actions(driver)
val menuElement = driver.findElement(By.id("menuh"))
action.moveToElement(menuElement).perform()
val subMenuElement = driver.findElement(By.cssSelector("#menuh li:nth-child(5)"))
action.moveToElement(subMenuElement).perform()
val earningsReportElement = driver.findElement(By.linkText("Earnings Report"))
action.moveToElement(earningsReportElement)
action.click()
action.perform()

Iterate through a list?

I have the following markup.
Edit: Added full markup
<div id="SelectList">
<div class="select-area-left"></div>
<div class="select-area-right"></div>
<div id="SelectedOption">Option0</div>
<ul id="ShowOptions">
<li id="ShowOption0">Option0</li>
<li id="ShowOption1">Option1</li>
<li id="ShowOption2">Option2</li>
<li id="ShowOption3">Option3</li>
<li id="ShowOption4">Option4</li>
<li id="ShowOption5">Option5</li>
<li id="ShowOption6">Option6</li>
<li id="ShowOption7">Option7</li>
<li id="ShowOption8">Option8</li>
<li id="ShowOption9">Option9</li>
<li id="ShowOption10">Option10</li>
<li id="ShowOption11">Option11</li>
<li id="ShowOption12">Option12</li></ul></div>
And i'm trying to use the following code to print out each list elements text.
List<WebElement> allElements = driver.findElements(By.xpath("//div[#id='SelectList']/ul"));
for (WebElement element: allElements) {
System.out.println(element.getText());
}
But its just given a blank output. Is there something i'm missing?
Try following code :
List<WebElement> allElements = driver.findElements(By.xpath("//div[#id='SelectList']/ul/li"));
for (WebElement element: allElements) {
System.out.println(element.getText());
}
Basically you missed to point li element in the xpath used. Above code should work for you.

Categories

Resources