Click Next link until pagination Next action is disabled in selenium webdriver - selenium

I want to verify elements in a row inside a table in by navigating each page through pagination.I am able to navigate to each page and assert element but the probelm is at last page the loop still continues even though the Next link is grayed out.
When Next link is disabled
<span>
<a class="next_btn inactive">NEXT ></a>
</span>
When Next link is enabled
<span>
<a class="next_btn" href="home.do?action=Next&start=10&end=20&sort=&
type=00&status=&fromDate=04/02/2017&toDate=05/02/2017&school=&
district=0009">NEXT ></a>
</span>
Actual Code
public void submissionType() throws Exception {
driver.findElement(By.linkText("NEXT >"));
while(true) {
processPage();
if (pagination.isDisplayed() && pagination.isEnabled()){
pagination.click();
Thread.sleep(100L);
} else
break;
}
}
private void processPage() {
String statusColumn="//td[#class='gridDetail'][2]";
List<WebElement> list = table.findElements(By.xpath(statusColumn));
for (WebElement checkbox : list) {
String columnName=checkbox.getText();
Asserts.assertThat(columnName,"File");
}
}

Instead of identifying the element with By.linkText("NEXT >"), try identifying it with By.cssSelector("a.next_btn").
When you use this approach, then when the object becomes disabled, its class name would change, and hence your object would no longer get identified and your loop would break.
Edit: Add try block and Catch NoSuchElement exception to avoid exceptions.

I know you already accepted an answer but one of the statements is not correct. The locator, By.cssSelector("a.next_btn"), will find both the enabled and disabled button so it will not cause the loop to break.
Looking at your code, I would offer a few suggestions/corrections.
.isEnabled() only really works on INPUT tags so testing for that doesn't really accomplish anything here.
Using Thread.sleep() is not a good practice. You can google some explanations but basically the problem is that it's an inflexible wait. If the element you are waiting for becomes available in 15ms, you are still going to wait 10s or whatever your sleep is set to. Using an explicit wait (WebDriverWait) is a best practice.
I would clean up your functions and write them like
public void submissionType()
{
WebDriverWait wait = new WebDriverWait(driver, 10);
By nextButtonLocator = By.cssSelector("a.next_btn:not(.inactive)");
List<WebElement> nextButton = driver.findElements(nextButtonLocator);
while (!nextButton.isEmpty())
{
processPage();
nextButton.get(0).click();
wait.until(ExpectedConditions.stalenessOf(nextButton.get(0))); // wait until the page transitions
nextButton = driver.findElements(nextButtonLocator);
}
}
private void processPage()
{
for (WebElement checkbox : table.findElements(By.xpath("//td[#class='gridDetail'][2]")))
{
Asserts.assertThat(checkbox.getText(), "File");
}
}

Related

Wait for element for certain amount of time

I have been experiencing one issue during test automation implementation. Particularly test checks if a hamburger menu is displayed.
So far I defined the element and subelement, and I need to really wait just one second, and not to waste time If I know that element will not be displayed after several seconds.
WebDriverWait wait = new WebDriverWait(getDriver(), 1);
WebElement hamMenu = el.findElement(By.xpath(HAMBURGER_MENU_GENERAL_XPATH));
How to implement the method findElement in the way it will try to find the element in one sec? I do not wish to stay longer... Thanks
Try this -
WebElement elem = new WebDriverWait(driver, 1).until(ExpectedConditions.visibilityOfElementLocated(By.xpath(HAMBURGER_MENU_GENERAL_XPATH)));
If I summarize your requirement is as follows :
Check if a hamburger menu is displayed only for 1 second : You need WebDriverWait with proper ExpectedConditions
Element may/not not be displayed after several seconds : You need to wrapup your code in a try-catch {} block to be able to proceed further in absence of the hamburger.
Youe effective code can be :
try {
WebElement hamburger = new WebDriverWait(getDriver(), 1).until(ExpectedConditions.visibilityOfElementLocated(By.xpath("HAMBURGER_MENU_GENERAL_XPATH")));
System.out.println("Hamburger is displayed in 1 sec");
//rest of your code
} catch (NoSuchElementException e){
System.out.println("Hamburger wasn't displayed in 1 sec");
//rest of your code
}
I got it. Thanks for all hints. This will wait just only for short time which is intended.
public boolean isHamMenuDisplayed(){
getDriver().manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
if (el.findElements(By.xpath(HAMBURGER_MENU_GENERAL_XPATH)).size() == 0)
return false;
else
return true;}

Why does Selenium "flicker" between finding and not finding a particular HTML element?

I'm using Specflow/Selenium to automate test of a web application I'm working on in the ASP.Net environment. Most of the 'button clicks' lead to complete page loads. I execute the following lines of code to execute when clicking such a button, but it's a flickering piece of code - sometimes it finds the element and other times it fails. Why is that?
public class CreateQuestionPOM : BasePOM
{
//Flickering find!
[FindsBy(How = How.XPath, Using = "//label[text()[contains(.,'True/False')]]")]
private IWebElement trueFalseOption;
[FindsBy(How = How.XPath, Using = "//a[#ct='Button' and #title='Next']")]
private IWebElement nextButton;
public CreateQuestionPOM(IWebDriver driver) : base(driver) { }
public void CreateTrueFalseQuestion()
{
trueFalseOption.Click();
nextButton.Click();
WebDriverWait wait = new WebDriverWait(GetDriver(), TimeSpan.FromSeconds(20));
wait.Until(driver1 => ((IJavaScriptExecutor)GetDriver()).ExecuteScript("return document.readyState").Equals("complete"));
}
}
The above method signature is similar to all button clicks that happen on the page. The above piece of code is called after a previous button is clicked. The method is very similar to the above - wait for document.readystate to be complete. But why does this flicker so often and what is the recommended solution?
There is no wait in your code, there is a wait.until(). When that code is executed, it is executed immediately and the until condition is checked. If the until condition is true, execution continues. Only if the until condition is false will there be a wait. If the code executes fast enough, the browser may not be transitioning to the next page before the until condition is checked. The until condition will pass because the current page (the page you clicked the element on) is already loaded. One thing you can try is to pick an element off the clicked page and wait for it to be stale. An element is stale when it is no longer in the DOM. When the next page is loaded, the elements on the previous page are stale. Try the code below and see if it helps.
public void CreateTrueFalseQuestion()
{
trueFalseOption.Click();
nextButton.Click();
WebDriverWait wait = new WebDriverWait(GetDriver(), TimeSpan.FromSeconds(20));
// when nextButton is stale you know the browser is transitioning...
wait.until(ExpectedConditions.stalenessOf(nextButton));
// ... then you wait for the new page to load
wait.Until(driver1 => ((IJavaScriptExecutor)GetDriver()).ExecuteScript("return document.readyState").Equals("complete"));
}

"Style" attribute not getting identified in Selenium Webdriver for the mentioned case

For the following html code in https://www.parcelhero.com/en-gb/courier-services/carriers/dhl, getattribute("style") fetches null value. Why?
<div class="dvPageShare" style="position: relative; top: -50px;">
Following is the Code used:
driver.get("https://www.parcelhero.com/en-gb/courier-services/carriers/dhl");
List <WebElement>SocialLink = driver.findElements(By.tagName("div"));
for (WebElement social : SocialLink)
{
if( social.getAttribute("class")!=null && social.getAttribute("class").equals("dvPageShare"))
{
System.out.println("Present");System.out.println(social.getAttribute("style"));
}
}
Take the EAFP approach. Find the element by class name and handle exceptions:
try {
WebElement social = driver.findElement(By.cssSelector("div.dvPageShare"));
System.out.println("Present");
System.out.println(social.getAttribute("style"));
} catch (NoSuchElementException ex) {
System.out.println("Not Present");
}
alecxe is using the right approach, I would just code it slightly differently. If there are no elements that match, code execution falls through the loop. You can specifically check for socialLinks.size() > 0, if you want... maybe log a message in that case. You'll have to decide what is best in your case.
List<WebElement> socialLinks = driver.findElements(By.cssSelector("div.dvPageShare"));
for (WebElement socialLink : socialLinks)
{
System.out.println("Present");
System.out.println(socialLink.getAttribute("style"));
}
This CSS Selector div.dvPageShare means find a DIV that has the class (.) dvPageShare.
I didn't try running your code but I did see that there are two DIVs with class = "dvPageShare" on that page, one of which did not have a style attribute. Maybe that's where the null is coming from?
CSS Selector reference. Learn them... they are very powerful and every automator should understand and use them.

wait for "loading" icon to disappear from the page

we are doing automation for web application and most of the scenario getting loading icon will appear at center of the page .. we need to wait for dis appear to loading icon
<div id="loading" style="display: none; visibility: hidden;">
<div></div>
<div></div>
Example : we are having search functionality their in most of scenario we are getting this loading icon.
selenium webdriver we are using: id we are getting for loading to complete is id= "loading"..please any give the solutions for the above issues am facing.
we have different functionality like click & sendkeys
Explicit Wait should help:
public static String waitForElementNotVisible(int timeOutInSeconds, WebDriver driver, String elementXPath) {
if ((driver == null) || (elementXPath == null) || elementXPath.isEmpty()) {
return "Wrong usage of WaitforElementNotVisible()";
}
try {
(new WebDriverWait(driver, timeOutInSeconds)).until(ExpectedConditions.invisibilityOfElementLocated(By
.xpath(elementXPath)));
return null;
} catch (TimeoutException e) {
return "Build your own errormessage...";
}
}
I have recently faced this issue. My solution might sound hacky but it worked pretty well in my case:
public static void loadingWait(WebDriver driver, WebElement loader) {
WebDriverWait wait = new WebDriverWait(driver, 5000L);
wait.until(ExpectedConditions.visibilityOf(loader)); // wait for loader to appear
wait.until(ExpectedConditions.invisibilityOf(loader)); // wait for loader to disappear
}
you can call this method after clicking on submit button. You have to pass driver, and loader web element to this method.
You can also wait till the ajax calls have been completed. Loading wheel disappears when all the ajax calls have completed (in most of the scenarios):
WebDriverWait wait = new WebDriverWait(d, timeOutSeconds);
wait.until(waitForAjaxCalls());
public static ExpectedCondition<Boolean> waitForAjaxCalls() {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return Boolean.valueOf(((JavascriptExecutor) driver).executeScript("return (window.angular !== undefined) && (angular.element(document).injector() !== undefined) && (angular.element(document).injector().get('$http').pendingRequests.length === 0)").toString());
}
};
}
I faced this issue and the solution is really simple :
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until( ExpectedConditions.invisibilityOfElementLocated(By.xpath("path_of_loader")));
Generally, you must have something like on your website :Image
so use path_of_loader = //div[#id='circular3dG'] .. You can also try searching using keywords like loader, spinner or use a page to inspect loader/spinner where it takes long to load the page.

WebDriver does not use latest page source

I'm running into problems when executing Selenium 2.18 WebDriver tests against an Oracle SSXA-based site, which translates to tons of popups, Ajax-loaded content and iframes. For a given page, based on manual observation, the page is initially loaded with an empty sslw_doc_content_id span (no text). About a second later, the span still exists and contains text.
To check that this page has loaded, I'm using a WebDriverWait with a Predicate that checks that the sslw_doc_content_id span has non-empty text:
new Predicate<WebDriver>() {
#Override
public boolean apply(final WebDriver input) {
return StringUtils.isNotEmpty(input.findElement(By.id("sslw_doc_content_id")).getText());
}
}
Somehow, WebDriver always finds the WebElement but always returns an empty string when calling WebElement.getText(). And so this predicate always evaluates to false.
Inspecting the page with Chrome or Firefox shows that the element exists and does have text. When debugging the predicate, I've observed that input.getPageSource() contains the span with no text on its first invocation, but that input.getPageSource() contains the span with some text on its second invocation (after the page has been ajax-refreshed).
Why doesn't WebDriver consider the refreshed page source on the second invocation?
Thanks!
You can try loop:
int seconds = 0;
for (int seconds =0; seconds<30; seconds++) {
if (apply(driver)){
break;
}
Thread.sleep(1000);
}
The above loop will check every second if text is there and do it for 30 seconds. If it finds it, it will escape the loop. You can still add one more check after:
if (!apply(driver)){
throw new RuntimeException("Expected text still not there");
}
Or another approach, which I am using: Whenewer I have page to load for long time, I select element which is loaded among the last on the page and check its presence the same way:
for (int seconds =0; seconds<30; seconds++){
try{
driver.findElement(By.id("lastelementonpage"));
}catch (Exception e){
Thread.sleep(1000);
}
}
It turns out that WebDriver does not allow access to hidden elements, and this span was hidden.
http://code.google.com/p/selenium/wiki/FrequentlyAskedQuestions#Q:_Why_is_it_not_possible_to_interact_with_hidden_elements?
I've resorted to using the JavaScript-based solution described in the above link.