When testing an ajax page there is a challenge how to wait till the page is loaded.
The way i found in the web is to wait explicitly for a certain element to load.
There is another way in htmlunit, which is to convert all asynchronous javascript to synchronous javascript.
client.setAjaxController(new NicelyResynchronizingAjaxController());
This is more generic, as we don't need to know exactly for which element to wait.
Is there a way to implement this with the firefoxdriver.
This is how you could wait for a specific element that is loaded in the DOM after a Ajax Request.
Suppose you have the following:
<div id="postAjaxRequest">This only appears after something request me!</div>
The all you had to do is with a started WebDriver and WebDriverWait element is the following:
WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10); // Starts a wait of a maximum 10 seconds.
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("postAjaxRequest")));
driver.findElement(By.id("postAjaxRequest")).click(); // or any other action
This is the simplest i could explain.
Related
I am using selenium web driver and I need to wait until all loaders disappear. I have 12 widgets on dashboard page and I need to wait until all widgets are loaded. Loader shows on each widget. I have used both following ways but nothing works and no errors, it just passes on to next statement.
new WebDriverWait(driver,60)
.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[contains(text(),'Loader')]")));
WebDriverWait wait2 = new WebDriverWait(driver,60);
wait2.until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("div.loader")));
As you are having total 12 widgets on dashboard page and you need to wait until all widgets are loaded you have to induce WebDriverWait for the invisibilityOfAllElements() and you can use either of the following Locator Strategies:
cssSelector:
new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfAllElements(driver.findElements(By.cssSelector("div.loader"))));
xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.invisibilityOfAllElements(driver.findElements(By.xpath("//div[#class='loader']"))));
I created a re-usable WebDriver method, but I can't for the life of me figure out how I can call a predefined Geb page CSS selector using WebDriver.
This method works, but I can't seem to call it using WebElement element:
static void WaitVisibilityOfElement(WebDriver driver, By cssSelector, int timeoutInSeconds) {
WebDriverWait Wait = new WebDriverWait(driver, timeoutInSeconds)
Wait.until(ExpectedConditions.visibilityOfElementLocated(cssSelector)).click()
}
This is the element I am trying to call, and I want to just be able to use the name of the element flipperCardOne, but if I do that it doesn't work.
flipperCardOne(wait:true) {$ (".flex-item:nth-child(5) .front > .w-100")}
Geb's selector results (the things returned from calls to $()) are called Navigators and are a wrapper around collections of Selenium's WebElements. Because Navigators can be created from more than just css selectors (you can chain multiple find() calls on them, you can base them off xpath expressions and you can filter contents of them by matching their text, just to give a number of examples) you cannot map one to one from a Navigator to a css selector. If your intention is to always wait for flipperCardOne to be visible before interacting with it then the idiomatic way to do that would be to use waitCondition content option:
flipperCardOne(wait:true, waitCondition: { it.displayed }) {$ (".flex-item:nth-child(5) .front > .w-100")}
Then you could just do flipperCardOne.click() and it would work.
And if you insist on using a method similar to what you listed in the question (and I'd argue that it's not the right thing to do) then you'd need something like:
static void WaitVisibilityOfElement(WebDriver driver, WebElement webElement, int timeoutInSeconds) {
WebDriverWait Wait = new WebDriverWait(driver, timeoutInSeconds)
Wait.until(ExpectedConditions.visibilityOf(webElement)).click()
}
and then call it like:
WaitVisibilityOfElement(browser.driver, flipperCardOne.singleElement, 5)
From my understanding, waitForAngular is executed on each step, and it waits for any kind of angular rendering and/or $http calls before proceeding to the next step.
My problem I am having is, I'm using Angularfire/Firebase as my backend, and in my tests when I click on a button for example - the waitForAngular is executed too fast, and then next step has occured before firebase has come back with a result.
Does anyone know a simple way to extend waitForAngular to also wait for any Angularfire call?. That would solve my problem and I could get rid of all of these dreaded sleep calls.
If you're using something like this
element(by.css('.btn')).click()
ptor.waitForAngular();
//execute something after
You can try converting it to a nested promise resolve pattern like this
var ptor = protractor.getInstance();
ptor.findElement(protractor.By.css('.btn')).click().then(function(){
//execute something after
});
I only have some basic info about firebase but haven't used it ever. But I guess this should help with promises/http requests.
What is the command in webdriver to wait for page to load fully before performing action on the page in CHROME browser?
PageLoadTimeOut is not waiting for the page load to complete in Chrome whereas it is working fine in firefox.
In Chrome, if webelement is there on the page, webdriver is performing the action on webelement while page is getting loaded. This is causing scripts to fail randomly with exception 'element is not clickable'.
Please let me know if there is any solution for this.
Thanks
You can use custom wait methods for an element to be enable or visible on the page.
For Example create a custom method isElementEnable using following code:
driver.findElement(locator).isEnabled();
Or use the following code to check if the element is visible on page:
driver.findElement(locator).isDisplayed();
pass your element locator as input parameter to the method.
Or Alternatively use implicit wait:
driver.manage().timeouts().implicitlyWait(number_of_seconds, TimeUnit.SECONDS);
Hope this will help.
You can use the JavaScriptExecuter.executeScript to get document.readyState,to compare it to complete,as a condition to WebDriverWait.Like this:
WebDriverWait wait = new ...;
wait.until(new ExpectedCondition<Boolean>(){
public Boolean apply(WebDriver driver) {
return (JavaScriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
});
Unfortunately, with Chrome if you have a alert on page,you will get a UnhandledAlertException.And this will not occur for Firefox
It's a really old question, but anyone having the same question might find this useful:
For chromedriver, it is best to use sleep method:
import time
# some of your code
time.sleep(2)
# here your program will wait for two seconds
# rest of your code
You can find an appropriate time span that will ensure your page loads and pass that time as parameter. But using too big time will make program slower.
Is there a better way to wait until all page is loaded,
my angular pages are loaded with promise, it means that if all ajaxs call haven't ended yet
there is a loader on the screen.
i'm currently using ptor.sleep(10000), like in the following example:
beforeEach(function(){
ptor = protractor.getInstance();
driver = ptor.driver;
ptor.get(base_url);
ptor.sleep(10000);
});
is there a better way to do it?
If you're using ng-if to hide/show your content when loading starts/finishes, you can use the following syntax to wait until a certain element appears on the page (i.e. ng-if will prevent the element from being in the DOM until the page finishes loading):
ptor.findElement(by.id('element-only-shown-after-loading')).then(function (myElement) {
// Your page should be loaded at this point
});