I have an element on a web page that is updated by AJAX almost immeditely after page load. I know what I expect the change to be and want Selenium to wait for the change and capture it. I am trying to use an explicit wait for this. However, I am getting a timeoutException as Selenium is not detecting the change.
I know I am properly selecting the element and value as I have used print statements. I've solved the issue using
Java Thead.sleep(1000)
and then using
driver.findElement(By.id("balance-sms")).getText()
but this is not an acceptable solution.
private void modalSend(String newBalence){
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(modalSendButton)); //this wait works fine
modalSendButton.click(); //this results in a page refresh
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.id("balance-sms")),newBalence));
//continue...
}
Try the locator using xpath and visibilityOfElementLocated with a few modifications :
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='balance-sms' and contains(text(),'" +newBalence +"')]")));
//continue...
Try with fluent wait like below instead of Thread.sleep
Wait wait = new FluentWait(WebDriver reference)
.withTimeout(timeout, SECONDS)
.pollingEvery(timeout, SECONDS)
.ignoring(Exception.class);
Related
I created few test cases on Selenium using Java. Unfortunately when I click an element on the page, before I could move on to any other action, I have to wait till the page loads.
I have tried driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);. Unfortunately this creates another problem. Even if the page loads, it waits 30 seconds before it started testing on the page.
What I found the best way is to send ESCAPE key to stop page load.
Is there anyway I could check if an element exists and when it does, send ESCAPE key to the browser to stop page load?
This part is bugging my mind as I have to wait till page loads before Java reads the next line of the code so I can't send ESCAPE key to browser till the page actually stops loading.
Edit
I have just tried using a new thread to do the job but it seems driver is completely locked out, can't do any process on it before page stops loading.
I'm out of ideas for the moment but I believe there should be a way.
Using timeouts() is causing whole test case to stop.
First I'd like to say this isn't a best practice. The selenium click method states that if the click triggers a page load, selenium will do its best to block until the page is loaded. Instead of clicking via the click method you could try sending the click event via JavaScript. Then wait for the element like normal.
You can try driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS); It is supposed to throw an error after timeout is over. I have never used it but maybe you can try and catch this error and continue with your test. But your page could end up in an unstable state with everything not loading and test interacts with elements.
I did it in C#, scenario is the same elsewhere.
Define driver like this:
var firefoxOptions = new FirefoxOptions();
firefoxOptions.PageLoadStrategy = PageLoadStrategy.None;
driver = new FirefoxDriver(firefoxOptions);
PageLoadStrategy.None means when open a URL, continue to next line regardless of the results and do not wait to load the page.
Usually, it takes some seconds to load a page and element appears, suppose I'm waiting for email_user element to appears:
int user_emailID = 0, popupAlert = 0;
do
{
float timeToWait = 0;
driver.Navigate().GoToUrl("https://stackoverflow.com");
do
{
await Task.Delay(500);
timeToWait += 0.5F;
user_emailID = driver.FindElements(By.XPath("//input[#id=\'user_email\']")).Count;
}
while (user_emailID == 0 && timeToWait < 10);
if (user_emailID == 1)
{
//Element exists now!do something and don't wait for page to load completely
}
}
while (user_emailID != 1);
More explanation: when open a URL, first loop check the presence of element every 0.5 second, if it appears, the loop stops. If after 10 seconds it couldn't find the element, the page will reloaded !!
Hope this get you the idea.
Remember, exception must not happen in your codes !!
I'm using webdriver(java) for a unique test where a page reloads itself when you log on, I've been unable to wait for the element to load because it is already there before the reload. So far the only way I've been able to get it to work is to use a thread.sleep, is there a way to listen for a page refresh?
One way to solve this is, to get a reference to the element you need, that appears both on the login-page and the reloaded page.
Then you can use the ExpectedConditions.stalenessOf to occur, and then you can be sure, that the element is removed from the DOM and a new element is created. Well, the last part is not guaranteed by this method, but at least you know that the old element is gone.
The code could look something like this:
WebElement elementOldPage = driver.findElement(By.id("yourid"));
... do login etc ...
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.stalenessOf(elementOldPage));
WebElement elementNewPage = driver.findElement(By.id("yourid"));
Building upon the accepted answer from Kim Schiller one might be interested in the following piece of code. It is surely not perfect due to the sleeps, so be free to suggest improvements to make it more bulletproof. Also note I'm no expert with selenium.
The if branch waits for the top level node in the html to go stale in case of a page reload. The else branch simply waits until the drivers url matches the request url in case we load a different page.
def safe_page_load(url):
if driver.current_url == url:
tmp = driver.find_element_by_xpath('/html')
driver.get(url)
WebDriverWait(driver, 2).until(ExpectedConditions.staleness_of(tmp))
else:
driver.get(url)
while(driver.current_url) != url:
sleep(0.3)
sleep(0.3)
Happy if I could help someone.
I was just wondering if there's an elegant way to utilize ExpectedConditions or something else to have my code wait for a page's source to contain a given string until a given timeout. I know I can use something like this if I wanted to use a specific element's locator ...
WebDriverWait wait = new WebDriverWait(driver,10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.linkText("foobar")));
But I wanted to accomplish this without using a locator for a specific element, and just use the whole page source as my reference instead. Any suggestions?
You cant have the all elements as a condition for waiting. When switching page weddriver automaticly wait for the page to load. WHen it has finished loading the HTML elements it continues. But it doesnt wait for JavaScript to execute. A lot of webpages today uses JavaScript to populate the webpage after the HTML has loaded.
What you should do is wait for every element you want to use.
wait.until(ExpectedConditions.refreshed(ExpectedConditions.visibilityOfElementLocated(by)));
or
wait.until(ExpectedConditions.refreshed(ExpectedConditions.elementToBeClickable(element))h;
You can wait for document's readyState to become complete. Run the javascript return document.readyState").equals("complete") against the web page that is loading.
void waitForLoad(WebDriver driver) {
ExpectedCondition<Boolean> pageLoadCondition = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(pageLoadCondition);
}
And then you can get the page source:
driver.getPageSource();
And then verify that the pageSource contains what you are looking for:
driver.getPageSource().contains("your element/tag");
I hope this helps!
Without depending on visibility, you could check if an element is present in the DOM:
WebDriverWait wait = new WebDriverWait(driver,10);
wait.until(ExpectedConditions.presenceOfElementLocated(By.tagName("html")));
If you want to refer to individual text, you can implement ExpectedCondition<T> and create your own condition class. The mentioned interface has access to the WebDriver (due to super-interface com.google.common.base.Function<WebDriver,T>).
In the method apply you could use the WebDriver and call method getPageSource() to have String presenting the page source. Check the String for whatever you prefer.
I am creating a test and having some issues. Here is the scenario. I use Selenium Web driver to fill out a form on Page1 and submit the form by clicking a button. Page2 starts loading... but the problem is, Page2 uses Google Analytics codes, and sometimes it takes forever for the page to stop loading.
Even though the expected element is already present, Selenium web driver does not proceed until the whole web page is fully loaded.
How do I make Selenium to move on to the next task or stop loading external javascript/css if the expected element is already present?
I tried tweaking the following settings but no luck.
driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
TEMPORARY SOLUTION: Scroll below for answer!
Give below approaches a shot.
driver.findElement(By.tagName("body")).sendKeys("Keys.ESCAPE");
or
((JavascriptExecutor) driver).executeScript("return window.stop");
Alternatively, you can also use WebDriverBackedSelenium as shown in the snippet below from Vincent Bouvier.
//When creating a new browser:
WebDriver driver = _initBrowser(); //Just returns firefox WebDriver
WebDriverBackedSelenium backedSelenuium =
new WebDriverBackedSelenium(driver,"about:blank");
//This code has to be put where a TimeOut is detected
//I use ExecutorService and Future<?> Object
void onTimeOut()
{
backedSelenuium.runScript("window.stop();");
}
Source: https://sqa.stackexchange.com/a/6355
Source: https://stackoverflow.com/a/13749867/330325
So, I reported to Selenium about these issues. And the temporary workaround is... messing with Firefox's timeout settings. Basically by default Firefox waits about 250 seconds for each connection before timing you out. You can check about:config for the details. Basically I cranked it down so Firefox doesn't wait too long and Selenium can continue as if the page has already finished loading :P.
Similar config might exist for other browsers. I still think Selenium should let us handle the pagetimeout exception. Make sure you add a star to the bug here: http://code.google.com/p/selenium/issues/detail?id=6867&sort=-id&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary, so selenium fixes these issues.
FirefoxBinary firefox = new FirefoxBinary(new File("/path/to/firefox.exe"));
FirefoxProfile customProfile = new FirefoxProfile();
customProfile.setAcceptUntrustedCertificates(true);
customProfile.setPreference("network.http.connection-timeout", 10);
customProfile.setPreference("network.http.connection-retry-timeout", 10);
driver = new FirefoxDriver(firefox, customProfile);
driver.manage().deleteAllCookies();
Once you have checked for the element and you know that it is present, you could either navigate to/load a different page (if the next tasks are on a different page) or if the tasks are on the same page (as you anyway do not need the elements that have not yet loaded), you could continue as usual - selenium will identify the elements which have already been loaded. This works for me when I work with feature rich pages.
Instead of using the webdriver click() to submit the form use jsexecutor and do a click. Jsexecutor does not wait for page load and you can with other actions.
As per the above scenario explained i feel its best to use the below wait command in the first page.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.id(>someid>)));
Once the required element is found in the first page next you can proceed to the second page.
As per the above scenario explained i feel its best to use the below wait command in the first page.
WebDriverWait wait = new WebDriverWait(driver, 10); WebElement element =
wait.until(ExpectedConditions.presenceOfElementLocated(By.id(>someid>)));
Once the required element is found in the first page next you can proceed to the second page.
Use explicit/webdriver wait----
WebDriverWait wt=new WebDriverWait(driver, 20);
wt.until(ExpectedConditions.elementToBeClickable(By.name("abc")));
"Register as new user" link text appears on home page , as soon as webdriver get it (driver.get) . But still it waits for entire page to load up to execute below line.
driver.findelement(By.linkText("Register as new user")).click();
how can it be possible that webdriver click on the element as soon as it appears on the page, no matter other elements appeared or not.
I am using: JAVA, Ubuntu.
I am not sure whether the implicit wait makes the driver wait till the page is fully loaded especially after opening an URL. But it is worth trying explicit wait. The below code makes the driver wait till the element becomes clickable then clicks on it. Should the element doesn't become clickable in the specified time(in the below example it is set to 30 seconds) then driver throws TimeoutException.
WebDriverWait wait = new WebDriverWait(driver, 30//unit time in seconds);
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Register as new user"))).click();
You can change the FireFoxDriver profile setting to make Firefox not wait for the full page to load after calling .click
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("webdriver.load.strategy", "unstable");
Bracket the wait.until ... statement like so:
turnOffImplicitWaits();
wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Register as new user"))).click();
turnOnImplicitWaits();