I am writing selenium framework with multiple environment support, and lower envs are slower and sometimes fail to load a page - completely blank page is loaded after 30s.
How can I add a global retry mechanism to try again in such scenario, other than modyfing every method that opens new page.
What such mechanism should do, refresh the page and continue? I have no good ideas.
You can build on dynamic function which includes pageload strategy and check if the document ready state is complete or not if these two conditions aren't met then u can reiterate the initialization process.
void waitForLoad(WebDriver driver) {
new WebDriverWait(driver, 30).until((ExpectedCondition) wd ->
((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete"));
}
Related
I am looking for function in Java +selenium where I can check or verify if page is fully loaded. I saw onLoad() of JS but nothing on java, is there is something for JAVA?
also I saw these:
WebDriver driver = new AnyDriverYouWant();
if (driver instanceof JavascriptExecutor) {
((JavascriptExecutor)driver).executeScript("yourScript();");
} else {
throw new IllegalStateException("This driver does not support JavaScript!");
}
but again JS and need to write script in JS
How to use JavaScript with Selenium WebDriver Java
update - also can try these solution too:
void waitForLoad(WebDriver driver) {
new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd -> ((JavascriptExecutor) wd).executeScript("return document.readyState").equals("complete")); }
from here https://stackoverflow.com/a/15124562/12115696
In order to determine if a page is fully loaded, you will need to identify which WebElements on the page indicate a loading status. For example, if there is a load mask of some type, you will want to wait until the load mask is hidden to verify that the page is fully loaded.
Here's a simple "Wait until loaded" function that utilizes the ExpectedConditions class:
Given the following HTML for a load mask:
<div id='load-mask' style='display: block'/>
You can use the following code to wait until the load mask is hidden:
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(seconds));
wait.Until(ExpectedConditions.InvisibilityOfElementLocated(By.Id("load-mask")));
Edit -- added a JavaScript-only wait function, as requested by the asker:
wait.until(driver=> ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete"));
This checks the document.readyState attribute in JavaScript, and completes the wait once readyState is set to complete.
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 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")));
I am using selenium webdriver along with TestNG in eclipse.The problem is the page relaods in the midway for some data and the time of this reload is flexible thats why I am not able apply explicit wait time.I want to make webdriver wait until this reload completes.
I am trying to do this through this code...but it is not working
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);
}
try the below code for handling page load/page refresh time outs
WebDriver driver = new FireFoxDriver();
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
please use latest version of chrome driver, as the page wait is not handled in older version of chrome driver.
Waiting for an indefinite time is not a good idea. Timing of a website is also a part of testing. If possible find out the Service Level Agreement of the "page" you are testing. If not run a speed test for the website(here is a method to test : http://tools.pingdom.com/fpt/ ) and use an average of time you get. If this also doesn't work the last option is to work with industry wide standards.
document.readyState() does not reflect the correct page load time(example- it does not wait for images/scripts to load fully). It is suggested and tested option to wait for an element on the page(preferrably the one you will operate upon in your next step of test). As others have suggested use WebDriverWait with expected conditions methods like "visibilityOf", "presenceOfElement" or many more and it should be fine.
You should use WebDriverWait and set the timeout to the maximum time you can wait. As soon as you discover that the page loaded the required data (e.g. by checking for visibility of a certain element), you may proceed with the test case.
See an example in the selenium docs.
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
For java 8 onwards:
JavascriptExecutor js = (JavascriptExecutor) driver;
new WebDriverWait(driver, 10).until(webDriver ->(js).executeScript("return document.readyState;").equals("complete"));
For java below 8 you can try the below solution from the below link. I am using it and it's working for me.
Wait for page load in Selenium
"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();