Selenium refresh - selenium

I am working on project where everything is saved in events so it took some time for server to respond for new data. I am using Fluent wait for pages using ajax, but this one doesn't use any ajax. So I want to refresh page check if new item is there if not refresh again. How this is achieved in Selenium 2?
I did this :
def accountsAfterCreating = 0
while (accountsAfterCreating <= existingAccounts) {
driver.navigate().refresh()
WebElement table = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.className("table"))
}
})
accountsAfterCreating = table.findElements(By.className("amount")).size()
}
Is it correct way?

Use Explicit wait like this In try catch block
try{
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));
}
catch()
{
driver.navigate().refresh()
}

I usually use this method to wait for any html tag. We can also specify the wait time.
public boolean waitForElement(WebElement ele, String xpath, int seconds) throws InterruptedException{
//returns true if the element appears within the time
//false when timed out
int t=0;
while(t<seconds*10){
if(ele.findElements(By.xpath(xpath)).size()>0)
return true;
else{
Thread.sleep(100);
t++;
continue;
}
}
System.out.println("waited for "+seconds+"seconds. But couldn't find "+xpath+ " in the element specified");
return false;
}

I came up with answer like this. This will work only on groovy because it is using closure
private boolean refreshUntil(Closure<Boolean> condition) {
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(8, TimeUnit.SECONDS)
.pollingEvery(200, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException)
wait.until(new Predicate<WebDriver>() {
boolean apply(WebDriver driver) {
driver.navigate().refresh()
if (condition()) {
return true
}
return false
}
})
return true
}
and calling this method
refreshUntil {
accountsBeforeCreation + 1 == driver.findElements(By.tagName("tr"))).size()
}

Related

Selenium java SafariDriver wait for page to load after click

When I run the following code, the execution abruptly ends unless I uncomment the Thread.sleep(). As result my code in the withdraw url servlet is not executed. The click is a submit button click which loads another page.
EventFiringWebDriver webDriver = new EventFiringWebDriver(new SafariDriver());
try {
webDriver.get("http://localhost:9988");
webDriver.findElement(By.id("amount")).sendKeys(new StringBuffer().append(amount.getRupees()).append('.').append(amount.getPaise()).toString());
webDriver.findElement(By.id("withdraw")).click();
//Thread.sleep(10000);
} finally {
webDriver.close();
}
What is the right way to make selenium wait till the page loads?
I am using the following selenium version
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>3.11.0</version>
Sounds like explicit waits might be what you need. There are a collection of ready-to-use conditions in the ExpectedConditions class (see https://www.seleniumhq.org/docs/04_webdriver_advanced.jsp for more). But once you understand how they work, making your own is pretty straightforward. The beauty of these is that unlike Thread.sleep(), once the condition is met, it'll immediately stop waiting.
I wrote out some specific examples I've used in the past for waiting for "page loads", and then get a little into how to make your own just in case it's useful to you:
If your page is light on the ajax content, and loads some static content once, you could implement an explicit wait condition to check the DOM's readyState property
// this could benefit being static so it doesn't create new classpath defs every invocation
public ExpectedCondition<Boolean> readyStateIsComplete() {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver webDriver) {
String readyState = (String) ((JavascriptExecutor) webDriver)
.executeScript("return document.readyState");
return readyState.equals("complete");
}
public String toString() {
return "page document's readyState flag to be complete";
}
};
}
This property only is "complete" once all static content is finished loading. Using it could be like:
// prepare me like this
WebDriverWait wait = new WebDriverWait(driver, maxSecondsToWait);
// Use me like this
wait.until(readyStateIsComplete());
The example above is good for the first time you load a page before all content finishes. If your page is heavy on the ajax content, maybe instead or in addition to you could try waiting for the ajax queue to reach zero, which can be done on an already loaded page that has ajax work it is doing.
public ExpectedCondition<Boolean> activeQueuesToFinish() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
// This is just a formatted javascript block with in-string indenting
String jScript = "if (A4J.AJAX) {" +
" with (A4J.AJAX) {" +
" var queues = A4J.AJAX.EventQueue.getQueues();" +
" for (var queueNames in queues) {" +
" return A4J.AJAX.EventQueue.getQueue(queueNames).getSize() <= 0;" +
" }" +
" }" +
" }" +
" return true;";
try {
return (Boolean) ((JavascriptExecutor) driver).executeScript(jScript);
} catch (WebDriverException e) {
return true;
}
}
public String toString() {
return "active queues to finish.";
}
};
If you use jquery, you could try this instead for letting current ajax work finish:
public ExpectedCondition<Boolean> allAjaxRequestsFinish() {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
return (Boolean) ((JavascriptExecutor) driver).executeScript("return jQuery.active == 0");
} catch (Exception e) {
return true;
}
}
public String toString() {
return "all ajax requests to finish.";
}
};
}
All these conditions or any condition you create in this template can be used for dynamic waiting in that same way:
wait.until(activeQueuesToFinish());
wait.until(allAjaxRequestsFinish());
Edit:
The "template" I mean is a function with this form:
public ExpectedCondition<Boolean> myCustomCondition(/* some arguments from the outside */) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
// Check something on the page and return either true or false,
// this method will be run repeatedly until either the time
// limit is exceeded, or true is returned
}
public String toString() {
return "a description of what this is waiting for";
}
};
}
Here's an example of how you could do this to wait on a specific element that may be holding up your page:
public ExpectedCondition<Boolean> waitForElementToHaveText(final WebElement element, final String expectedText) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
try {
return element.getText().equals(expectedText);
} catch (Exception e) {
return false; // catchall fail case
}
}
public String toString() {
return "an element to have specific text";
}
};
}

How to wait untill a page is dim after clicking a button?

How to wait until a page is dim(loading) after clicking a button? I tried following options but not succeeded yet. I have to capture transaction timings.
1) Implicit Wait
(driver.manage().timeouts().implicitlyWait(20L, TimeUnit.SECONDS);)
2) Explicit Wait
(wait = new WebDriverWait(driver, 200);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("(//a[#ardbn='z3Btn_TDS_Next']/div/img)[position()<3]")));)
3) One of my own function
public void waitForPageLoaded() {
ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete"); } };
Wait<WebDriver> wait = new WebDriverWait(driver,30); try { wait.until(expectation); } catch(Throwable error) { fail("Timeout waiting for Page Load Request to complete."); } }
Wait till invisibility of Loading box.
Suppose locator/id/xpath of Loading box is id = loader, Then
By locator = By.id("loader");
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(timeOutInSeconds, TimeUnit.SECONDS)
.pollingEvery(pollingIntervalInSeconds, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class)
.ignoring(StaleElementReferenceException.class);
wait.until(ExpectedConditions.invisibilityOfElementLocated(locator));

How to use clickandwait in Selenium Webdriver using Java?

I am trying to click on the object, to show the list of value pop-up.
I used the following script, but unable to populate the list value pop-up.
Driver.findElement(By.xpath(OR.getProperty(Object))).click();
Thread.sleep(1000L);
Is there any other way to click and wait for the object?
Driver.findElement(By.xpath(OR.getProperty(Object))).click();
WebDriverWait wait = new WebDriverWait(Driver, timeoutInSeconds);
wait.until(ExpectedConditions.elementToBeClickable(By.id("yourId")));
There are other conditions like visibilityOf so choose the one which suits you most - documentation here.
String mainWindowHandle = driver.getWindowHandle();
System.out.println(mainWindowHandle);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(OR.getProperty(Object)));
Driver.findElement(By.xpath(OR.getProperty(Object))).click();
PageUtil.sleep(3000);
Set<String> s1 = driver.getWindowHandles();
Iterator<String> ite = s1.iterator();
while (ite.hasNext()) {
String popupHandle = ite.next().toString();
System.out.println(popupHandle + " Present Pop Up window name");
if (!popupHandle.contains(mainWindowHandle)) {
driver.switchTo().window(popupHandle);
}
}
WebDriverWait wait = new WebDriverWait(Driver, timeoutInSeconds);
wait.until(ExpectedConditions.elementToBeClickable(By.id("yourId")));
Driver.findElement(By.id("yourId")).click();
driver.switchTo().window(mainWindowHandle);
After clicking you can wait using FluentWait,
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
refer this for more info
I'm not quite familiar with java syntax, but I'll give you php code and you can write similar. The idea is to find HTML element by tag and get it's id BEFORE YOU CLICK. Then AFTER THE CLICK wait for the id to change.
It looks like this:
class MySeleniumCondition extends WebDriverExpectedCondition{
public static function htmlElementIdIsNot($htmlElementId) {
return new WebDriverExpectedCondition(
function ($driver) use ($htmlElementId) {
$htmlElement = $driver->findElement(WebDriverBy::tagName('html'));
return $htmlElementId != $htmlElement->getId();
}
);
}
}
// .............. somehere in a class:
public function waitForNewPage($oldHtmlElementId, $time = 10){
try{
$this->driver->wait($time)->until(
MySeleniumCondition::htmlElementIdIsNot(
$oldHtmlElementId
)
);
return true;
}catch(TimeOutException $e){
return false;
}
}
// use this only when you are sure the page will reload
public function clickAndWait(WebDriverBy $locator, $time = 10){
$webElement = $this->driver->findElement($locator);
$oldHtmlElement = $driver->findElement(WebDriverBy::tagName('html'));
$oldHtmlElementId = $oldHtmlElement->getId();
$webElement->click();
$this->waitForNewPage($oldHtmlElementId, $time);
return true;
}

webdriver implicitWait not working as expected

In webdriver code if i use thread.sleep(20000). It's waiting for 20 seconds, and my code also works fine.
To archive the same if i use implicit wait like
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
It's not waiting forcefully for 20 seconds and goes to next steps just in 3 to 4 seconds. and page still loading.
This is wired situation as i am using fluent wait to find some elements. if the elements still loading on the page it does not show error and make the test passed.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(50, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("jxxx"));
}
});
But if i say wrong id it waits for 50 seconds but other test got passed without clicking.. it is not showing any error.
My Question is how I should avoid Thread.sleep() as other selenium methods are not helping me..
Use below method to wait for a element:
public boolean waitForElementToBePresent(By by, int waitInMilliSeconds) throws Exception
{
int wait = waitInMilliSeconds;
int iterations = (wait/250);
long startmilliSec = System.currentTimeMillis();
for (int i = 0; i < iterations; i++)
{
if((System.currentTimeMillis()-startmilliSec)>wait)
return false;
List<WebElement> elements = driver.findElements(by);
if (elements != null && elements.size() > 0)
return true;
Thread.sleep(250);
}
return false;
}
And below method is to wait for page load:
public void waitForPageLoadingToComplete() throws Exception {
ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript(
"return document.readyState").equals("complete");
}
};
Wait<WebDriver> wait = new WebDriverWait(driver, 30);
wait.until(expectation);
}
Let's assume you are waiting for a page to load. Then call the 1st method with waiting time and any element which appears after page loading then it will return true, other wise false. Use it like,
waitForElementToBePresent(By.id("Something"), 20000)
The above called function waits until it finds the given element within given duration.
Try any of below code after above method
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
or
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));
Update:
public boolean waitForTextFiled(By by, int waitInMilliSeconds, WebDriver wdriver) throws Exception
{
WebDriver driver = wdriver;
int wait = waitInMilliSeconds;
int iterations = (wait/250);
long startmilliSec = System.currentTimeMillis();
for (int i = 0; i < iterations; i++)
{
if((System.currentTimeMillis()-startmilliSec)>wait)
return false;
driver.findElement(By.id("txt")).sendKeys("Something");
String name = driver.findElement(by).getAttribute("value");
if (name != null && !name.equals("")){
return true;
}
Thread.sleep(250);
}
return false;
}
This will try entering text in to the text field till given time in millis. If getAttribute() is not suitable in your case use getText(). If text is enetered then it returns true. Put maximum time that u can wait until.
You might want to try this for an element to become visible on the screen.
new WebDriverWait(10, driver).until(ExpectedConditions.visibilityOfElementLocated(By.id("jxxx")).
In this case, wait time is a maximum of 10 seconds.

Selenium wait until document is ready

Can anyone let me how can I make selenium wait until the time the page loads completely? I want something generic, I know I can configure WebDriverWait and call something like 'find' to make it wait but I don't go that far. I just need to test that the page loads successfully and move on to next page to test.
I found something in .net but couldn't make it work in java ...
IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
Any thoughts anyone?
Your suggested solution only waits for DOM readyState to signal complete. But Selenium by default tries to wait for those (and a little bit more) on page loads via the driver.get() and element.click() methods. They are already blocking, they wait for the page to fully load and those should be working ok.
Problem, obviously, are redirects via AJAX requests and running scripts - those can't be caught by Selenium, it doesn't wait for them to finish. Also, you can't reliably catch them via readyState - it waits for a bit, which can be useful, but it will signal complete long before all the AJAX content is downloaded.
There is no general solution that would work everywhere and for everyone, that's why it's hard and everyone uses something a little bit different.
The general rule is to rely on WebDriver to do his part, then use implicit waits, then use explicit waits for elements you want to assert on the page, but there's a lot more techniques that can be done. You should pick the one (or a combination of several of them) that works best in your case, on your tested page.
See my two answers regarding this for more information:
How I can check whether page is loaded completely or not in web driver
Selenium Webdriver : Wait for complex page with javascript to load
Try this code:
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
The above code will wait up to 10 seconds for page loading. If the page loading exceeds the time it will throw the TimeoutException. You catch the exception and do your needs. I am not sure whether it quits the page loading after the exception thrown. i didn't try this code yet. Want to just try it.
This is an implicit wait. If you set this once it will have the scope until the Web Driver instance destroy.
See the documentation for WebDriver.Timeouts for more info.
This is a working Java version of the example you gave :
void waitForLoad(WebDriver driver) {
new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
}
Example For c#:
public static void WaitForLoad(IWebDriver driver, int timeoutSec = 15)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}
Example for PHP:
final public function waitUntilDomReadyState(RemoteWebDriver $webDriver): void
{
$webDriver->wait()->until(function () {
return $webDriver->executeScript('return document.readyState') === 'complete';
});
}
Here's my attempt at a completely generic solution, in Python:
First, a generic "wait" function (use a WebDriverWait if you like, I find them ugly):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
Next, the solution relies on the fact that selenium records an (internal) id-number for all elements on a page, including the top-level <html> element. When a page refreshes or loads, it gets a new html element with a new ID.
So, assuming you want to click on a link with text "my link" for example:
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
For more Pythonic, reusable, generic helper, you can make a context manager:
from contextlib import contextmanager
#contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
And then you can use it on pretty much any selenium interaction:
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
I reckon that's bulletproof! What do you think?
More info in a blog post about it here.
I had a similar problem. I needed to wait until my document was ready but also until all Ajax calls had finished. The second condition proved to be difficult to detect. In the end I checked for active Ajax calls and it worked.
Javascript:
return (document.readyState == 'complete' && jQuery.active == 0)
Full C# method:
private void WaitUntilDocumentIsReady(TimeSpan timeout)
{
var javaScriptExecutor = WebDriver as IJavaScriptExecutor;
var wait = new WebDriverWait(WebDriver, timeout);
// Check if document is ready
Func<IWebDriver, bool> readyCondition = webDriver => javaScriptExecutor
.ExecuteScript("return (document.readyState == 'complete' && jQuery.active == 0)");
wait.Until(readyCondition);
}
WebDriverWait wait = new WebDriverWait(dr, 30);
wait.until(ExpectedConditions.jsReturnsValue("return document.readyState==\"complete\";"));
For C# NUnit, you need to convert WebDriver to JSExecuter and then execute the script to check if document.ready state is complete or not. Check below code for reference:
public static void WaitForLoad(IWebDriver driver)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
int timeoutSec = 15;
WebDriverWait wait = new WebDriverWait(driver, new TimeSpan(0, 0, timeoutSec));
wait.Until(wd => js.ExecuteScript("return document.readyState").ToString() == "complete");
}
This will wait until the condition is satisfied or timeout.
For initial page load I have noticed that "Maximizing" the browser window practically waits until page load is completed (including sources)
Replace:
AppDriver.Navigate().GoToUrl(url);
With:
public void OpenURL(IWebDriver AppDriver, string Url)
{
try
{
AppDriver.Navigate().GoToUrl(Url);
AppDriver.Manage().Window.Maximize();
AppDriver.SwitchTo().ActiveElement();
}
catch (Exception e)
{
Console.WriteLine("ERR: {0}; {1}", e.TargetSite, e.Message);
throw;
}
}
than use:
OpenURL(myDriver, myUrl);
This will load the page, wait until completed, maximize and focus on it. I don't know why its like this but it works.
If you want to wait for page load after click on next or any other page navigation trigger other then "Navigate()", Ben Dyer's answer (in this thread) will do the work.
In Nodejs you can get it via promises...
If you write this code, you can be sure that the page is fully loaded when you get to the then...
driver.get('www.sidanmor.com').then(()=> {
// here the page is fully loaded!!!
// do your stuff...
}).catch(console.log.bind(console));
If you write this code, you will navigate, and selenium will wait 3 seconds...
driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...
From Selenium documentation:
this.get( url ) → Thenable
Schedules a command to navigate to the given URL.
Returns a promise that will be resolved when the document has finished loading.
Selenium Documentation (Nodejs)
Have a look at tapestry web-framework. You can download source code there.
The idea is to signalize that page is ready by html attribute of body. You can use this idea ignore complicated sue cases.
<html>
<head>
</head>
<body data-page-initialized="false">
<p>Write you page here</p>
<script>
$(document).ready(function () {
$(document.body).attr('data-page-initialized', 'true');
});
</script>
</body>
</html>
And then create extension of Selenium webdriver (according to tapestry framework)
public static void WaitForPageToLoad(this IWebDriver driver, int timeout = 15000)
{
//wait a bit for the page to start loading
Thread.Sleep(100);
//// In a limited number of cases, a "page" is an container error page or raw HTML content
// that does not include the body element and data-page-initialized element. In those cases,
// there will never be page initialization in the Tapestry sense and we return immediately.
if (!driver.ElementIsDisplayed("/html/body[#data-page-initialized]"))
{
return;
}
Stopwatch stopwatch = Stopwatch.StartNew();
int sleepTime = 20;
while(true)
{
if (driver.ElementIsDisplayed("/html/body[#data-page-initialized='true']"))
{
return;
}
if (stopwatch.ElapsedMilliseconds > 30000)
{
throw new Exception("Page did not finish initializing after 30 seconds.");
}
Thread.Sleep(sleepTime);
sleepTime *= 2; // geometric row of sleep time
}
}
Use extension ElementIsDisplayed written by Alister Scott.
public static bool ElementIsDisplayed(this IWebDriver driver, string xpath)
{
try
{
return driver.FindElement(By.XPath(xpath)).Displayed;
}
catch(NoSuchElementException)
{
return false;
}
}
And finally create test:
driver.Url = this.GetAbsoluteUrl("/Account/Login");
driver.WaitForPageToLoad();
Ben Dryer's answer didn't compile on my machine ("The method until(Predicate<WebDriver>) is ambiguous for the type WebDriverWait").
Working Java 8 version:
Predicate<WebDriver> pageLoaded = wd -> ((JavascriptExecutor) wd).executeScript(
"return document.readyState").equals("complete");
new FluentWait<WebDriver>(driver).until(pageLoaded);
Java 7 version:
Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
}
};
new FluentWait<WebDriver>(driver).until(pageLoaded);
I tried this code and it works for me. I call this function every time I move to another page
public static void waitForPageToBeReady()
{
JavascriptExecutor js = (JavascriptExecutor)driver;
//This loop will rotate for 100 times to check If page Is ready after every 1 second.
//You can replace your if you wants to Increase or decrease wait time.
for (int i=0; i<400; i++)
{
try
{
Thread.sleep(1000);
}catch (InterruptedException e) {}
//To check page ready state.
if (js.executeScript("return document.readyState").toString().equals("complete"))
{
break;
}
}
}
The wait for the document.ready event is not the entire fix to this problem, because this code is still in a race condition: Sometimes this code is fired before the click event is processed so this directly returns, since the browser hasn't started loading the new page yet.
After some searching I found a post on Obay the testing goat, which has a solution for this problem. The c# code for that solution is something like this:
IWebElement page = null;
...
public void WaitForPageLoad()
{
if (page != null)
{
var waitForCurrentPageToStale = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForCurrentPageToStale.Until(ExpectedConditions.StalenessOf(page));
}
var waitForDocumentReady = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
waitForDocumentReady.Until((wdriver) => (driver as IJavaScriptExecutor).ExecuteScript("return document.readyState").Equals("complete"));
page = driver.FindElement(By.TagName("html"));
}
`
I fire this method directly after the driver.navigate.gotourl, so that it gets a reference of the page as soon as possible. Have fun with it!
normaly when selenium open a new page from a click or submit or get methods, it will wait untell the page is loaded but the probleme is when the page have a xhr call (ajax) he will never wait of the xhr to be loaded, so creating a new methode to monitor a xhr and wait for them it will be the good.
public boolean waitForJSandJQueryToLoad() {
WebDriverWait wait = new WebDriverWait(webDriver, 30);
// wait for jQuery to load
ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
try {
Long r = (Long)((JavascriptExecutor)driver).executeScript("return $.active");
return r == 0;
} catch (Exception e) {
LOG.info("no jquery present");
return true;
}
}
};
// wait for Javascript to load
ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState")
.toString().equals("complete");
}
};
return wait.until(jQueryLoad) && wait.until(jsLoad);
}
if $.active == 0 so the is no active xhrs call (that work only with jQuery).
for javascript ajax call you have to create a variable in your project and simulate it.
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;
}
}
I executed a javascript code to check if the document is ready. Saved me a lot of time debugging selenium tests for sites that has client side rendering.
public static boolean waitUntilDOMIsReady(WebDriver driver) {
def maxSeconds = DEFAULT_WAIT_SECONDS * 10
for (count in 1..maxSeconds) {
Thread.sleep(100)
def ready = isDOMReady(driver);
if (ready) {
break;
}
}
}
public static boolean isDOMReady(WebDriver driver){
return driver.executeScript("return document.readyState");
}
public boolean waitForElement(String zoneName, String element, int index, int timeout) {
WebDriverWait wait = new WebDriverWait(appiumDriver, timeout/1000);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element)));
return true;
}
Like Rubanov wrote for C#, i write it for Java, and it is:
public void waitForPageLoaded() {
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return (((JavascriptExecutor) driver).executeScript("return document.readyState").toString().equals("complete")&&((Boolean)((JavascriptExecutor)driver).executeScript("return jQuery.active == 0")));
}
};
try {
Thread.sleep(100);
WebDriverWait waitForLoad = new WebDriverWait(driver, 30);
waitForLoad.until(expectation);
} catch (Throwable error) {
Assert.fail("Timeout waiting for Page Load Request to complete.");
}
}
In Java it will like below :-
private static boolean isloadComplete(WebDriver driver)
{
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
|| ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
The following code should probably work:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfAllElementsLocated(By.xpath("//*")));
If you have a slow page or network connection, chances are that none of the above will work. I have tried them all and the only thing that worked for me is to wait for the last visible element on that page. Take for example the Bing webpage. They have placed a CAMERA icon (search by image button) next to the main search button that is visible only after the complete page has loaded. If everyone did that, then all we have to do is use an explicit wait like in the examples above.
public void waitForPageToLoad()
{
(new WebDriverWait(driver, DEFAULT_WAIT_TIME)).until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver d) {
return (((org.openqa.selenium.JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete"));
}
});//Here DEFAULT_WAIT_TIME is a integer correspond to wait time in seconds
Here's something similar, in Ruby:
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until { #driver.execute_script('return document.readyState').eql?('complete') }
You can have the thread sleep till the page is reloaded. This is not the best solution, because you need to have an estimate of how long does the page take to load.
driver.get(homeUrl);
Thread.sleep(5000);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(userName);
driver.findElement(By.xpath("Your_Xpath_here")).sendKeys(passWord);
driver.findElement(By.xpath("Your_Xpath_here")).click();
I Checked page load complete, work in Selenium 3.14.0
public static void UntilPageLoadComplete(IWebDriver driver, long timeoutInSeconds)
{
Until(driver, (d) =>
{
Boolean isPageLoaded = (Boolean)((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete");
if (!isPageLoaded) Console.WriteLine("Document is loading");
return isPageLoaded;
}, timeoutInSeconds);
}
public static void Until(IWebDriver driver, Func<IWebDriver, Boolean> waitCondition, long timeoutInSeconds)
{
WebDriverWait webDriverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
webDriverWait.Timeout = TimeSpan.FromSeconds(timeoutInSeconds);
try
{
webDriverWait.Until(waitCondition);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
For the people who need to wait for a specific element to show up. (used c#)
public static void WaitForElement(IWebDriver driver, By element)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
wait.Until(ExpectedConditions.ElementIsVisible(element));
}
Then if you want to wait for example if an class="error-message" exists in the DOM you simply do:
WaitForElement(driver, By.ClassName("error-message"));
For id, it will then be
WaitForElement(driver, By.Id("yourid"));
Are you using Angular? If you are it is possible that the webdriver doesn't recognize that the async calls have finished.
I recommend looking at Paul Hammants ngWebDriver.
The method waitForAngularRequestsToFinish() could come in handy.