wait for "loading" icon to disappear from the page - selenium

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.

Related

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

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");
}
}

Element not found - Selenium

I have written a piece of code to login into an application which is working fine. Now I have to click an add button, and I have tried it by Id, XPath, ClassName but it just gives me the exception of element not found. I thought I should apply an explicit wait, but it also did not work. Please check my code below:
public static void Login()
{
Browser.Url = "http://example.com";
_username = Browser.FindElement(By.Id("UserName"));
var password = Browser.FindElement(By.Id("Password"));
var loginbtn = Browser.FindElement(By.ClassName("btn-primary"));
_username.SendKeys("admin");
password.SendKeys("123");
loginbtn.Click();
var supplierTab = Browser.FindElement(By.Id("mainSupplier"));
supplierTab.Click();
WebDriverWait wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(20));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
try
{
return d.FindElement(By.Id("btnAddSupplier_SupplierForm"));
}
catch
{
return null;
}
});
var addbtn = Browser.FindElement(By.Id("btnAddSupplier_SupplierForm"));
addbtn.Click();
}
This always gives an exception on the second last line of code that element not found.
Here is the HTML:
Try the following
public static void Login()
{
Browser.Url = "http://example.com";
_username = Browser.FindElement(By.Id("UserName"));
var password = Browser.FindElement(By.Id("Password"));
var loginbtn = Browser.FindElement(By.ClassName("btn-primary"));
_username.SendKeys("admin");
password.SendKeys("123");
loginbtn.Click();
//I think you have mentioned the iframe exist and assuming the element is inside the iframe do the following. If not skip the SwitchTo() part
//you can use name, css to identify the iframe
Browser.SwitchTo().Frame(Browser.FindElement(By.XPath("xpath for the iframe")));
var supplierTab = Browser.FindElement(By.Id("mainSupplier"));
supplierTab.Click();
WebDriverWait wait = new WebDriverWait(Browser, TimeSpan.FromSeconds(20));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
{
return d.FindElement(By.Id("btnAddSupplier_SupplierForm"));
});
//if you think the id is not unique try using xpath or css
//even though you added an explicit wait you never used it
myDynamicElement.Click();
}
Sometimes the element will be existing in the source code but will not be visible for selenium to perform a click operation. Try the below code which will wait until the element is visible:
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(20));
IWebElement element = wait.Until(
ExpectedConditions.ElementIsVisible(By.Id("btnAddSupplier_SupplierForm")));
element.Click();
Not sure if this would help, but try calling this function before you click on Add button:
void waitForPageLoad(WebDriver driver)
{
ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoadCondition);
}
A NoSuchElementException is thrown when the locating mechanism used is not available in the dom.
A TimeoutException is thrown when your expected condition fails to be true within the time limit. An expected condition can be anything, (exists,visibility,attribute value etc...).
First you want to figure out if the element's locating mechanism you are using is indeed not found in the dom. Here is a good way to manually find out.
Open chrome and navigate to the page.
Open chrome dev tools and click on the console tab.
In the text box type $x("//*[#id='btnAddSupplier_SupplierForm']") and hit enter. This will run an xpath query, basically you are looking for any element that has an id attribute with value "btnAddSupplier_SupplierForm".
If an element appears in the console and is the correct element then it's likely that you are trying to find an element in the dom before the dom is finished loading. If no element appears in the console then you have a bad locator.
Please report your findings.

wait on handler registering - selenium

There is a html page with button, and my selenium test is testing, that there is an action executed, when the button is clicked.
The problem is, that it looks like the click happens before the javascript is executed - before the handler is bound to the page. The consequence is, that the selenium test will click on the button, but no action happens.
I can solve this problem by repeatedly trying to click and then observe, if the desired action happened (some element is present on page, typically). I'd like to hear that there are some more elegant solutions...
There is no clear way to say "wait until element X has such-and-such handler"; this is a limitation of JavaScript and the DOM (see for example Get event listeners attached to node using addEventListener and jQuery find events handlers registered with an object), and for that matter a selenium Expected Condition can't be created, at least not trivially.
I've resorted to time.sleep(0.5).
You can write some logic to handle this.
I have write a method that will return the WebElement and this method will be called three times or you can increase the time and add a null check for WebElement
Here is an example
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("https://www.crowdanalytix.com/#home");
WebElement webElement = getWebElement(driver, "homekkkkkkkkkkkk");
int i = 1;
while (webElement == null && i < 4) {
webElement = getWebElement(driver, "homessssssssssss");
System.out.println("calling");
i++;
}
System.out.println(webElement.getTagName());
System.out.println("End");
driver.close();
}
public static WebElement getWebElement(WebDriver driver, String id) {
WebElement myDynamicElement = null;
try {
myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By
.id(id)));
return myDynamicElement;
} catch (TimeoutException ex) {
return null;
}
}

Selenium NoAlertPresentException

I'm trying to handle dialog (Ok Cancel type) with selenium WebDriver. So my aim is to click "Ok" button.
Scenario is:
Click button for invoking dialog
button.click();
Try to accept
webDriver.switchTo().alert().accept();
But I'm always getting NoAlertPresentException and seeing that dialog closes almost immediately.
It seems to me that Selenium automatically closes dialog and when I want to accept, there is nothing to accept.
I'm sorry for my bad English.
The usual cause of this issue is that Selenium is too quick and tries to accept an alert that has not yet been opened by the browser. This can be simply fixed by an explicit wait:
button.click();
WebDriverWait wait = new WebDriverWait(driver, 5);
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
alert.accept();
Step 1:
public boolean isAlertPresent(){
boolean foundAlert = false;
WebDriverWait wait = new WebDriverWait(driver, 0 /*timeout in seconds*/);
try {
wait.until(ExpectedConditions.alertIsPresent());
foundAlert = true;
System.out.println("isAlertPresent : " +foundAlert);
} catch (TimeoutException eTO) {
foundAlert = false;
System.out.println("isAlertPresent : " +foundAlert);
}
return foundAlert;
}
Step 2:
public boolean tocheck_POP_Dialog()
{ Alert alert;
try
{
alert=driver.switchTo().alert();
}
catch(NoSuchElementException elementException)
{
return false;
}
alert.accept(); //Close Alert popup
return true;
}
Step 3 :
if(dummyPage.isAlertPresent())
{
dummyPage.tocheck_POP_Dialog();
}
public boolean isAlertPresent(){
try{
Alert a = new WebDriverWait(driver, 10).until(ExpectedConditions.alertIsPresent());
if(a!=null){
System.out.println("Alert is present");
driver.switchTo().alert().accept();
return true;
}else{
throw new Throwable();
}
}
catch (Throwable e) {
System.err.println("Alert isn't present!!");
return false;
}
}
Use explicit wait to check the alert and then do the operation. This might help you. :)
Generally it happens because Selenium commands run too quick and it tries to close the alert before it is open. Hence, adding a delay after click event should resolve the issue. Also, if you are using Safari browser for your test, there is some issue with SafariDriver in handling alerts. SafariDriver cannot handle alerts should provide you more details.
Some additional info. for future readers of this thread:
If this exception persists even after the wait aspect is addressed, please check if the following sequence of steps is effective in the test script:
the underlying Html page's DOM is queried/parsed for some purpose (e.g. to look for Form errors)
(before the) driver.switch_to.alert is attempted
When an Alert is shown over an Html page, if the Alert is overlooked and the DOM underlying the Html page is queried first, the Webdriver appears to loose track of the Alert & causes the Exception.
This was observed with: geckodriver 0.21.0, Firefox 66.0b10 (64-bit) ; python 3.6.1 Selenium driver 3.14 (for Python).
Performing (2) before (1) was found to resolve the issue.

Suggestions for getting Selenium to play nice with Bootstrap modal fade?

I'm working to live life the BDD way. I'm using Cucumber (with Selenium) and happen to be using Twitter Bootstrap modals in my application.
While running Cucumber tests, I was getting a "Selenium::WebDriver::Error::MoveTargetOutOfBoundsError" error. After much searching, debugging and general despair, I have concluded that it has to do with the use of the "fade" parameter in my Bootstrap modals. If I use "fade", the error is thrown:
<div class="modal hide fade" id="info-share-edit-modal" style="display: none;">
.
.
.
</div>
If I remove "fade", then Selenium is full of happiness and my tests clear:
<div class="modal hide" id="info-share-edit-modal" style="display: none;">
.
.
.
</div>
So, I am now removing "fade" from my various modals. But, this makes me sad because I like the fade effect.
Has anyone else experienced problems using Selenium with fade in Bootstrap modals? If so, is there some clever way of getting the two to work nicely together?
By the way (not sure if it matters), I'm Rails 3.2.3, Firefox 13.0.1, and Ubuntu 12.04LTS.
I did a quick test with inserting a WebDriverWait that takes a look at the opacity of the modal. It seems to work, but time will tell as (at least for me) it's an intermittent problem. Here's my implementation in Java.
//Ensure the modal is done animating
new WebDriverWait(driver, 5).until(
new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
return webDriver.findElement(By.id("videoModal")).getCssValue("opacity").equals("1");
}
}
);
I solved it this way (using c#). It is fast and hasn't failed once.
public static void WaitForModal(this RemoteWebDriver driver)
{
using (driver.NoImplicitWait())
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(d => d.FindElements(By.ClassName("modal-backdrop").Count == 0);
}
}
NoImplicitWait is used to temporarily disable the driver implicit wait.
public static NoImplicitWait NoImplicitWait(this IWebDriver driver)
{
return new NoImplicitWait(driver);
}
public sealed class NoImplicitWait : IDisposable
{
private readonly IWebDriver _driver;
public NoImplicitWait(IWebDriver driver)
{
_driver = driver;
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
}
public void Dispose()
{
_driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
}
}
Put in a flag so that in the test environment it doesn't fade, but it does in every other environment.
c# code
I had the same problem and this code is working for me since 2+ months, no more crash.
public static void WaitForModal(this IWebDriver driver)
{
wait.Until<IWebDriver>((d) =>
{
if (driver.FindElements(By.ClassName("modal-backdrop")).Count == 0)
{
return driver;
}
return null;
});
}
It waits until it finds no more IWebElement that have a class of "modal-backdrop".
Improving on user1965252's answer, this worked for me. Just replace the-modal-id with your modal div id.
new WebDriverWait(driver, TIME_OUT_IN_SECONDS).until(and(
new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
return webDriver.findElement(id("the-modal-id"))
.getCssValue("opacity").equals("0");
}
},
numberOfElementsToBe(cssSelector("div.modal-backdrop"), 0)
));
What I generally do is assert against some content that should be visible on the modal (or not visible when it is fading out):
expect(page).to have_content('My Modal Header')
expect(page).to have_no_content('My Modal Header')
It's important to use .to have_no_content and not .not_to have_content, as have_no_content will wait for a period for the thing to be true.
In a pinch, you can also check for modal CSS selectors. Bootstrap adds an in class when the modal is visible:
expect(page).to have_selector('.modal.in')
expect(page).to have_no_selector('.modal.in')
In a selenium test case when application opens the bootstrap modal, add a pause command to ask selenium to pause for one second before interacting with content of your modal:
Command: pause /
Target: 1000 /
Value: (leave empty)