How to wait until page load without browser stopped respnding? - selenium

Using C# I was trying to pause execution until the page load after login so I used this code:
for (int second = 0; ; second++)
{
if (second >= 60) Assert.Fail("timeout");
try
{
if (driver.FindElement(By.Id("footer")).Displayed) break;
}
catch (Exception)
{ }
Thread.Sleep(1000);
}
But I get system error that the browser Firefox stopped responding apparently on the Thread.Sleep(1000); line so how I prevent that ?
is there another way to pause execution other than thread.sleep() ?
Edit:
I used now
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
but it execute inconstantly without waiting 10 seconds !! why ??

One soultion is using a custom WebDriverWait with an expected condition like `titleIs'. This means the driver will poll the page for a predefined amount of time waiting for the page title to match what you expect it to be. In Java it would be like so:
public Boolean waitForPageIsLoaded(String title) {
return new WebDriverWait(driver, 60).until(ExpectedConditions.titleIs(title));
}

Related

How do i tell Selenium to wait until report get ready to download

After the selection of date from the date picker,clicking on 'View Report' button and then its take a time to generate the report and then it download the report.. My following code is working without an error but how do i use fluent wait instead of Thread.sleep(20000),(last line in below code). For fluent or explicit wait i ask to wait for what condition? Also wanted to verify whether the file has been downloaded or not with assertion. Any help will be appreciated.
public void generateReport() throws Exception {
clickDatePicker.click();
log.info("Select the Date from datepicker");
Select month = new Select(selectMonth);
month.selectByValue("0");
log.info("Selected the Month from datepicker");
Select year = new Select(selectYear);
year.selectByValue("2020");
log.info("Selected the Year from datepicker");
act.moveToElement(selectDate).click().build().perform();
buttonViewReport.click();
log.info("Finally clicked on Get Report button ");
Thread.sleep(20000);
}
Check the below method, which will make sure the script will wait until the download is started (for max of the minutes specified in the method call)
public void waitUntilDownloadStarted(WebDriver driver, int maxWaitTimeInMinutes) throws InterruptedException {
// Store the current window handle
String mainWindow = driver.getWindowHandle();
// open a new tab
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.open()");
// switch to new tab
// Switch to new window opened
for(String winHandle : driver.getWindowHandles()){
driver.switchTo().window(winHandle);
}
// navigate to chrome downloads
driver.get("chrome://downloads");
Instant startTime = Instant.now();
int elapsedTime = (int) Duration.between(startTime, Instant.now()).toMinutes();
// wait until the download is started
while ( (Long)js.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelectorAll('#downloadsList downloads-item').length") == 0) {
Thread.sleep(1000);
elapsedTime = (int) Duration.between(startTime, Instant.now()).toMinutes();
if (elapsedTime > maxWaitTimeInMinutes) {
break;
}
}
// close the downloads tab2
driver.close();
// switch back to main window
driver.switchTo().window(mainWindow);
}
Tested as below.
waitUntilDownloadStarted(driver, 10);
Does anything appears like that your download has been generated? or inspect any change in HTML. then you can use the following code to wait until change appears.
WebDriverWait wait=new WebDriverWait(driver, 20000);
wait.until(ExpectedConditions.numberOfElementsToBe(locator, number));
where 20000 is time in milliseconds

Selenium Java (proper wait for new page to load)

It's not a question but rather a sharing of information (i think many people will use it)
For few days tried to make one best solution (without sheninigans :-D ) to wait for new page to load, after click etc. Ofc no old days Thread.sleep or implicit waits
Some people suggested to wait until a last element from new page loads, some suggested to use JS executor (document.readyState solution) which will sometimes not work (in my case, it was always giving complete response)
Found another solution, to check when a reference to element on current page will throw StaleElementReferenceException. But... in this case the page didn't manage to load after this exception.
What i did? combined both solutions together and this always does a trick for me... One make sure that document isn't in a ready state (cause throws staleElementReferenceException) and another immediately after that checks till the page fully loads and gives readyState == complete
while(true) {
try {
//it's just an interaction (can be any) with element on current page
anyElementFromCurrentPage.getText();
} catch (StaleElementReferenceException e) {
break;
}
waitForLoad(driver);
return this;
}
void waitForLoad(WebDriver driver) {
new WebDriverWait(driver, 30).until((ExpectedCondition<Boolean>) wd ->
((JavascriptExecutor) wd).executeScript("return
document.readyState").equals("complete"));
}
hope some people will use this bulletproof solution :-)
So I work in C# but Java is similar. This is currently what I use even though its marked as "obsolete".
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
wait.Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.Name("elementNameHere")));

Selenium : Handle a window that popups up randomly

We have a feature that collects customer feedback. For this , when the user logs out , a window pops up up randomly - not every time for every customer.
I want to handle this in my automation code.
Currently, at the log out, I'm expecting a window and switching to it and that code is failing when the popup window doesn't show up.
What's the best way to handle this .
This is what I have so far ...
public static void waitForNumberOfWindowsToEqual(final int numberOfWindows) {
ExpectedCondition<Boolean> expectation = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return (driver.getWindowHandles().size() == numberOfWindows);
}
};
WebDriverWait wait = new WebDriverWait(driver, BrowserFactory.explicitWait);
wait.until(expectation);
}
I would handle the absence of popup window with a try/catch. Here is an example:
try {
WebDriverWait winwait = new WebDriverWait(driver, 3);
String mainWindow = driver.getWindowHandle();
// wait for 2 windows and get the handles
Set<String> handles = winwait.until((WebDriver drv) -> {
Set<String> items = drv.getWindowHandles();
return items.size() == 2 ? items : null;
});
// set the context on the last opened window
handles.remove(mainWindow);
driver.switchTo().window(handles.iterator().next());
// close the window
driver.close();
// set the context back to the main window
driver.switchTo().window(mainWindow);
} catch (TimeoutException ex) {
System.out.println("No window present within 3 seconds");
}
If possible, the ideal thing to do would be to have a look through the source to work out whether the popup window will appear, however if this isn't achievable you could take the following approach:
// Get the number of windows open before clicking the log out button.
int numberOfWindowsBeforeLogOut = driver.getWindowHandles().size();
// Click the log out button.
logOutButton.click();
// Check how many windows are open after clicking the log out button.
int numberOfWindowsAfterLogOut = driver.getWindowHandles().size();
// Now compare the number of windows before and after clicking the log out
// button in a condition statement.
if (numberOfWindowsBeforeLogOut < numberOfWindowsAfterLogOut) {
// If there is a new window available, switch to it.
driver.switchTo().window(titleOrWindowHandle);
}
In case you don't get the required window, the code will throw a TimeoutException. So, put wait.until(expectation) inside a try block and catch the exception. In code,
try {
wait.until(expectation);
} catch (TimeoutException ex) {
System.out.println("Nowindow This Time");
}

Popup freezes Selenium Webdriver until the popup is manually closed

I'm having problems automating tests on an internal website. In some cases, a popup will freeze the test until I manually close the popup. After the popup is opened, no code is run, not even System.out.println's.
driver.findElement(By.id("top_toolbarSALTkA7_Aras_Tbi_promote")).click();
System.out.println("test");
I have tried multiple ways of handling the popup, but no code at all is run after the click(), and it seems it never times out.
Tried:
1.
((JavascriptExecutor) driver).executeScript("return document.getElementById('top_toolbarSALTkA7_Aras_Tbi_promote', 'onClick')");
2.
Set<String> windowHandles = driver.getWindowHandles();
for(String handle : windowHandles)
{
driver.switchTo().window(handle);
if (driver.getTitle().contains(title))
{
System.out.println("- (Page title is: " + driver.getTitle() + ")");
break;
}
}
3.
driver.switchTo().alert();
4.
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
If I close the popup, the test will continue with the System.out.println and then continue until finshed.
I'm using Selenium Webdriver 2.48.2 with FireFox 31.0, programming is Java. Any ideas what can be done? (It's not possible to change the website)
Finally found the solution!!! Found it in the Selenium official user group: https://groups.google.com/forum/#!searchin/selenium-users/popup%7Csort:relevance/selenium-users/eDqPiYoJ9-Q/kRI67cCVe5wJ
Solution is to start a new thread that waits a couple of seconds, and then presses enter (or in my case first tabs to the "OK" button). Just call the function before the popup is opened.
public static final void prepareToPressEnterKey(int seconds, int tabs) {
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(new Runnable() {
public void run() {
try {
Robot robot = new Robot();
for (int i=0; i<tabs; i++)
{
robot.keyPress(KeyEvent.VK_TAB);
TimeUnit.SECONDS.sleep(1);
robot.keyRelease(KeyEvent.VK_TAB);
}
robot.keyPress(KeyEvent.VK_ENTER);
TimeUnit.SECONDS.sleep(1); //press for 1 sec
robot.keyRelease(KeyEvent.VK_ENTER);
} catch (AWTException | InterruptedException e) {
System.out.println("Prepare to Press Enter Exception");
}
}
},
seconds,
TimeUnit.SECONDS);
scheduledExecutorService.shutdown();
}
Still, if there are any better solutions I'd very much like to know. Thanks!
Just disable popup. I mean you need to call the next script inside the current browser context (executeScript - I guess in your, Java binding case):
document.alert = window.alert = alert = () => {};

How to make Selenium WebDriver wait for page to load when new page is loaded via JS event

I'm working on automating a site which has a number of links which load new pages via a JS event. Basically, there are elements which are clickable, clicking on one causes some JavaScript to run and this leads to a form being submitted and routing to a new page.
Now if these were just standard HTML links there would be no problem as Selenium is smart enough to tell that there's a new page coming and to wait to do things. But as good as it is, Selenium can't tell that the clicks in this instance are leading to new pages to load so it doesn't wait and just keeps going. As such it doesn't wait for the new page, tries to find elements which aren't there and my tests all fail. Bummer.
As a temporary solution I'm just pausing the program for three seconds like so:
oldPageDriver.clickThatButton();
try {
Thread.sleep(3000);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
newPageDriver = new NewPageDriver(driver);
newPageDriver.doStuffOnNewPage();
And this works, sort of. I don't like it because it's "hacky," and just interrupting the program instead of doing something smarter. Because the delay is hard coded at three seconds I get failures if the link is working but just slow. I've considered something like an implicit wait but that accomplishes the same thing and I've not found a solid, workable answer in Java anywhere after a considerable amount of looking.
So, can anyone suggest a way around this? Specifically, how to make Selenium know that a new page is expected and to wait until it's available?
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!
Explicit waits are what you need;
http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp
You can directly add this to your test or you may want to DRY it up, especially if there is a common wait expectation such as the disappearance of a spinning icon.
You could extend the click method to always wait after clicking or if following page objects, add a wait_until_loaded method to a base page class. There many other valid approaches but dependent on how the AUT is implemented
Simple ready2use snippet, working perfectly for me
static void waitForPageLoad(WebDriver wdriver) {
WebDriverWait wait = new WebDriverWait(wdriver, 60);
Predicate<WebDriver> pageLoaded = new Predicate<WebDriver>() {
#Override
public boolean apply(WebDriver input) {
return ((JavascriptExecutor) input).executeScript("return document.readyState").equals("complete");
}
};
wait.until(pageLoaded);
}