How to reproduce the Selenium Error - The HTTP request to the remote WebDriver timed out after 60 seconds - selenium

I am encountering the same error described in Selenium Error - The HTTP request to the remote WebDriver timed out after 60 seconds.
In order to better understand the problem, I need to create a minimal sample that reproduces the bug - an html page and a console app that uses Selenium to open it.
My question is: How exactly can I reproduce the bug, i.e. create an experimental program that intentionally triggers this bug?
Edit: In case it helps, according to IEDriver. Download. HTTP request to the remote WebDriver server timed out after 60 seconds:
The problem here is that when IE is in the process of downloading a file, the readyState of the browser never moves from interactive to complete

You could try to add a web page which includes a button control, in the button click event, you can call a web API to get data. In the web API method, add Thread. Sleep () method to stop the executing thread for a given amount of time (more than the request time). Then, if you trigger the button click event using Selenium WebDriver, it will show this error.
Code like this:
Code in mvc view:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script>
$(function () {
$("#buttonSearchPro").click(function () {
$.ajax({
url: "#Url.Action("GetData", "Home")",
async: false,
success: function (data) {
alert(data);
}
});;
});
});
</script>
<input type="button" id="buttonSearchPro" class="btn btnAction" value="Download" />
Code in MVC controller:
public ActionResult GetData()
{
Thread.Sleep(70000000);
return Json("OK", JsonRequestBehavior.AllowGet);
}
Code in console application:
private const string URL = #"http://localhost:65330/Home/Index";
private const string IE_DRIVER_PATH = #"D:\Downloads\webdriver\IEDriverServer_x64_3.14.0";
static void Main(string[] args)
{
//EdgeWebDriver();
InternetExplorerTest();
}
public static void InternetExplorerTest()
{
try{
var options = new InternetExplorerOptions()
{
InitialBrowserUrl = URL,
IntroduceInstabilityByIgnoringProtectedModeSettings = true
};
var driver = new InternetExplorerDriver(IE_DRIVER_PATH, options);
driver.Navigate();
//find the button and trigger click event.
driver.FindElementById("buttonSearchPro").Click() ;
driver.Close(); // closes browser
driver.Quit(); // closes IEDriverServer process
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.WriteLine("OK");
Console.ReadKey();
}
the result like this:

Related

NavManager.NavigateTo(); 404 status code under phone usage

I got a problem with NavManager.NavigateTo(); for Blazor webassembly application The scenario is the following:
I have a drop-down menu with possible website language translations and when the user wants to change the website language he should access a Web API controller action which will set the culture into the website cookies via the drop-down menu.
Let me share some code.
Here is the UI part from the Razor component
<div class="languageChanger">
<select class="form-select" #bind="this.Culture">
#foreach (var culture in cultures)
{
<option value="#culture">#this.Localizer[culture.Name]</option>
}
</select>
</div>
And here is the C# code part ot the Razor Component
CultureInfo[] cultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("bg-BG")
};
public CultureInfo Culture
{
get => CultureInfo.CurrentCulture;
set
{
if (CultureInfo.CurrentCulture != value)
{
var js = (IJSInProcessRuntime)this.JsRuntime;
js.InvokeVoid("SimeonValevPortfolioCulture.set", value.Name);
var uri = new Uri(this.NavManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var query = $"?cultureName={Uri.EscapeDataString(value.Name)}&" + $"redirectUri={Uri.EscapeDataString(uri)}";
this.NavManager.NavigateTo($"api/Culture/SetCulture" + query, forceLoad: true);
}
}
}
And here is the API Controller action
[HttpGet]
public IActionResult SetCulture(string cultureName, string redirectUri)
{
if (cultureName != null)
{
this.HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(cultureName)), new CookieOptions()
{
Expires = DateTimeOffset.UtcNow.AddMonths(1),
});
}
return this.LocalRedirect(redirectUri);
}
When I run the application locally, the controller action is accessed correctly and also when I deployed the application, the api action is correctly accessed from Google Chrome under Windows 10 OS. But via phone, under Android(Chrome web browser) and iOS(Safari web browser) the user is not able to access the API action. When he try to change the website culture the only thing which he can get from that operation is 404 status code. I noticed that when he try to update the drop-down value, he receive the following URL into the browser:
https://MySiteName.com/api/Culture/SetCulture?cultureName=bg-BG&redirectUri=%2F
And after that the application returns 404 status code
The conclusion which I get is somehow the api action could not be accessed only from phones. The issue is not faced under laptop usage.
Please let me know is there something which I missed.
Regards,
Simeon Valev
P.S. If it will be much better for you, I can share the website URL, it is hosted. Let me know
I fix the issue by creating a standard GET request. I apply the code changes.
Now it work properly.
#code {
private string currentCulture;
CultureInfo[] cultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("bg-BG")
};
protected override async Task OnInitializedAsync()
{
this.currentCulture = CultureInfo.CurrentCulture.Name;
await base.OnInitializedAsync();
}
public async Task OnCultureChanged(ChangeEventArgs e)
{
var cultureName = e.Value.ToString();
var js = (IJSInProcessRuntime)this.JsRuntime;
js.InvokeVoid("SimeonValevPortfolioCulture.set", cultureName);
var response = await this.HttpClient.GetFromJsonAsync<CompletedOperationViewModel>($"api/Culture/SetCulture/{cultureName}");
this.NavManager.NavigateTo(this.NavManager.Uri, forceLoad: true);
await response.DisplayMessage(this.JsRuntime);
}
}

Capture httpresponse object from webBrowser control

I need to capture the response content after the request is sent from webBrowser control.
When I have httpAnalyzer running, I am able to capture some important data (raw data) in response content that is passed back to webBrowser control.
Any ideas?
More info:
I have an internal site which uses flash to generate reports. I was able to automate page loading and simulate button clicking that produce the report. When I use the httpAnalyzer, I am able to see raw data that I need to capture; but I don't know how to actually get to response object.
I used FiddlerCore: http://fiddler2.com/fiddlercore
private void button_click()
{
Thread myThread = new Thread(delegate()
{
fiddlerRun();
});
myThread.Start();
}
private void fiddlerRun()
{
#region AttachEventListeners
Fiddler.FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oS)
{
String s1 = oS.GetResponseBodyAsString(); // this is where response is catched
//I know that response must contain specific word - if it is there- catch it!
if (s1.Contains("License") )
{
//do my stuff with response
//...
//stop Fiddler
Fiddler.FiddlerApplication.Shutdown();
System.Threading.Thread.Sleep(750);
}
};
#endregion AttachEventListeners
System.Diagnostics.Debug.WriteLine("Starting FiddlerCore...");
Fiddler.CONFIG.IgnoreServerCertErrors = false;
try
{
Fiddler.FiddlerApplication.Startup(8877, true, true);
}
catch { }
}

How to pass through window asking for basic auth credentials that appears when click link redirecting from HTTP to HTTPS?

I have a website where most of pages are normally used via HTTP but some other pages are available only via HTTPS. Site is protected by basic auth (credentials are the same for HTTP and HTTPS pages).
When I open any HTTP page in browser (either FF or Chrome) and click link that leads to HTTPS page, browser shows alert that asks for basic auth credentials.
I have same issue with Webdriver (either FF or Chrome):
When I visit http://username:password#some_domain.com and click link that leads to HTTPS page, browser alert window that asks for basic auth credentials appears. Selenium doesn't "remember" credentials that were entered for HTTP page.
How can I follow this sequence of actions with Webdriver? If it's not possible what can you advice?
FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("network.http.phishy-userpass-length", 255);
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", hostname);
Driver = new FirefoxDriver(profile);
hostname is your URL (example.com) then try to
Driver.Navigate().GoToUrl(http://user:password#example.com);
The best solution I've been able to come up with so far is create a new Thread that handles a timeout. As WebDriver doesn't return control on FF and other certain browsers, I can call the thread handler that then uses Robot to enter in the credentials and press enter (could also use AutoIt here). Then the control is returned back to WebDriver to continue with script.
//put this where it belongs, say calling a new url, or clicking a link
//assuming necessary imports
int pageLoadTimeout = 10;
String basicAuthUser = "user";
String basicAuthPass = "pass";
String url = "https://yourdomain.com";
WebDriver driver = new FirefoxDriver();
TimeoutThread timeoutThread = new TimeoutThread(pageLoadTimeout);
timeoutThread.start();
driver.get(url);
//if we return from driver.get() call and timeout actually occured, wait for hanlder to complete
if (timeoutThread.timeoutOccurred){
while (!timeoutThread.completed)
Thread.sleep(200);
}
else {
//else cancel the timeout thread
timeoutThread.interrupt();
}
public class TimeoutThread extends Thread {
int timeout;
boolean timeoutOccurred;
boolean completed;
public TimeoutThread(int seconds) {
this.timeout = seconds;
this.completed = false;
this.timeoutOccurred = false;
}
public void run() {
try {
Thread.sleep(timeout * 1000);
this.timeoutOccurred = true;
this.handleTimeout();
this.completed = true;
}
catch (InterruptedException e) {
return;
}
catch (Exception e){
System.out.println("Exception on TimeoutThread.run(): "+e.getMessage());
}
}
public void handleTimeout(){
System.out.println("Typing in user/pass for basic auth prompt");
try {
Robot robot = new Robot();
//type is defined elsewhere - not illustrating for this example
type(basicAuthUser);
Thread.sleep(500);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
Thread.sleep(500);
type(basicAuthPass);
Thread.sleep(500);
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
}
catch (AWTException e) {
System.out.println("Failed to type keys: "+e.getMessage());
}
}
}

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.

Selenium Webdriver sessionId or check if all browser windows are closed

Is there a way to see if all the browser windows are closed? I see that if you call driver.quit() or driver.close() on the WebDriver, the sessionId becomes null. Is there a way to check that?
I don't want to make a call to a closed or quit driver as it throws a WebDriverException. So I want to check to see the state of the browser before continuing on.
Just set
driver=null;
everytime you quit the browser and than check
if (browser!=null){
//Attention: this comand is not supported
//as far as i know ;)
driver.doSomething();
}
or
try{
}catch (NullPointerException e)
e.printStackTrace();
System.err.print"DAMN";
}
or receive a NullPointerException ;)
public bool InstanceExist
{
get
{
if (Instance != null)
{
try
{
return (Instance.WindowHandles != null); // allways returns true if browser instance exist or thrown error
}
catch (Exception e)
{
return false;
// means that browser was closed by user
}
}
return false; // means that it wasn't created yet or was closed by developer programmally
}
}
You need to check 3 situations:
driver wasnt created
driver was closed by developer
browser was closed by user, but driwer instance still exists
All of those situations is checked with this code.
I think the cleanest way to detect if all windows are closed is smth like:
boolean allWindowsClosed = webDriver.getWindowHandles().isEmpty();
getWindowHandles returns a set of window handles for all open windows - see http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/WebDriver.html#getWindowHandles()
Actually calling getWindowHandles while the browser windows is gone will raise an "UnreachableBrowserException".
You have to put the call into a try-catch block and handle that error. Actually that is the only known WORKING workournd for catching unexpected browser windows closes. I have a static method in a config class doing my driver handling: I restart my browser like this:
protected static void loadPages() {
if (driver == null || driver.toString().contains("null")) { //null refers to an missing session id
driver = new FirefoxDriver();
//load all my page objects like
loginpage = new LoginPage(driver);
//....
//....
}
try {
if (driver.getWindowHandles() == null || driver.getWindowHandles().isEmpty()){ //will cause an UnreachableBrowserException if the browser really is not avalable.
try { //you actually dont need this try catch block
driver.quit();
} catch (Exception e) {
System.err.println("Quitting levtover driver did not work.");
}
driver = null; //you have to set the driver to null
loadPages();
}
} catch (UnreachableBrowserException ube) {
driver = null; //like above set to null to make sure no driver left
}
}
Now, ofc your current test will fail but you will be able to go on with the rest of them.
in C#
public void BrowserCheck()
{
try
{
var h = webDriver.WindowHandles;
return; // no problem
}
catch // browser window is closed so re-init it
{
webDriver.Quit();
WebDriverInit(); // your init code
}
}