Does Selenium WebElement.Click() wait until the next page is loaded? - java

I tell Selenium to wait until it sees an element - Selenium sees it
I tell Selenium to click on this element, it is a button to link to a new page - Selenium click on it.
The problem is that after clicking it, Selenium will then wait until the next page is fully loaded (the page sometimes loads in a second, or waits for ages, I think it's a problem with Zen Desk Live Chat on that page).
When it is fully loaded it will then throw an error and say that the element it clicked on cannot be seen (naturally it can't because it is now on a new page)
I have tried changing the wait time with
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
however this doesn't help.
I have also tried
wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath(element)));
However this has the same problem.
Below is the code I am currently using.
try {
wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath(element)));
WebElement we = driver.findElement(By.xpath(element));
we.click();
System.out.println("Clicked: " + element);
}catch (Exception e){
System.out.println(e.getMessage());
}
I expect that once the element has been clicked on, that Selenium just carries on without caring if the next page has loaded up or not.
However what happens is when the 2nd page loads up, sometimes the page gets stuck "waiting for widget-mediator.zopim.com" and Selenium will not progress past the click() line until the the WebDriverWait time has expired (60 seconds)
After the 60 seconds has expired I see this error in the Console Output:
[1561374309.111][SEVERE]: Timed out receiving message from renderer: 60.000
[1561374309.112][SEVERE]: Timed out receiving message from renderer: -0.002
Is something else happening here? Or does Click() wait until the page has loaded, if that click takes it to a new page? If it does is there a way to tell it to stop waiting? I have other code to check if the page has loaded or not, but I don't need Click() to do this.
Thanks in advance.

Selenium’s (or more correctly, WebDriver’s) behavior on click is governed by the W3C WebDriver Specification. In that document, the full algorithm is defined for what happens when an element click is requested. In general, if the click will navigate to a new page, the driver will wait for that new page to be “loaded” (scare quotes intentional) according to the page load strategy until the page load timeout.
The page load strategy defaults to “normal”, or waiting for the document’s readyState to be complete. If you set it to “none” in the capabilities requested during driver instantiation, the driver will not wait at all. Choosing that route would mean you would need to handle all synchronization for pages being loaded. Note there is a third page load strategy, “eager”, but at the time of this writing, not all WebDriver implementations (most notably chromedriver) support it.
You can adjust the page load timeout at runtime in your Selenium code. One approach might be to lower the timeout to a relatively low value for the duration of clicking on this particular element, then restoring it to its prior value afterward. The drawback here is that you will have to catch the timeout exception that is thrown when the page load times out before continuing.

Related

driver.get(url) vs driver.navigate().to(url);

Google's Answer:
get() is used to navigate particular URL(website) and wait till page load. driver. navigate() is used to navigate to particular URL and does not wait to page load.
Selenium Documentation:
The document.readyState property of a document describes the loading state of the current document. By default, WebDriver will hold off on responding to a driver.get() (or) driver.navigate().to() call until the document ready state is complete
My query is in Google it was said, navigate method doesnot wait till the page loads which was not in line with the point added from Selenium Documentation.
Please help me to understand.
The first thing we do when run the script is to open the browser and load the web page. We use commonly driver.get(“url”); to load the webpage. Every time we use this command, the page will be refreshed.
We can also use driver.navigate().to(“url’); to load the webpage. Both the commands work in the same way in terms of behavior. But the navigate().to() also have the other functions such as navigate().forward(), navigate().back() and navigate().refresh().
So the difference is driver.get() never stores history whereas driver.navigate().to() stores browser history so as to be used for other commands forward and back etc.
In single page applications while navigate().to() navigates to the page by changing URL like doing forward/backward, get() refreshes page.
More info here - Difference between webdriver.get() and webdriver.navigate()
In simple words get() method in the WebDriver interface extends the SearchContext and is defined as:
/**
* Load a new web page in the current browser window. This is done using an HTTP POST operation,
* and the method will block until the load is complete.
* This will follow redirects issued either by the server or as a meta-redirect from within the
* returned HTML.
* Synonym for {#link org.openqa.selenium.WebDriver.Navigation#to(String)}.
*/
void get(String url);
Hence you can use:
driver.get("https://www.google.com/");
On the other hand, navigate() is the abstraction which allows the WebDriver instance i.e. the driver to access the browser's history as well as to navigate to a given URL. The methods along with the usage are as follows:
to(java.lang.String url): Load a new web page in the current browser window.
driver.navigate().to("https://www.google.com/");
to(java.net.URL url): Overloaded version of to(String) that makes it easy to pass in a URL.
refresh(): Refresh the current page.
driver.navigate().refresh();
back(): Move back a single "item" in the browser's history.
driver.navigate().back();
forward(): Move a single "item" forward in the browser's history.
driver.navigate().forward();
//Convenient
driver.get("https://selenium.dev");
//Longer way
driver.navigate().to("https://selenium.dev");
28/08/2022
There is no difference between the two, just that one is the long form and the other is the short form of Java.
https://www.selenium.dev/documentation/webdriver/browser/navigation/

ExplicitWait taking more time if an element removed from DOM

I'm automating this website But facing the issue with ExplicitWaitConditions to manage the time.
Scenario is When i click on Login link or Submit button after send username, It shows a loader during the process, once process has completed the loader get removed from DOM.
I have used condition for invisibilityOfElementLocated like below
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
But this can't predict correct time it taking more time (not exectly 60 sec but around 15-20 or may be 30 sec.) then allow to execute next command.
The same line i have to put before 4 commands to do complete login process. So it seems to consumed around 90 second to do login.
If i do not use Explicitwait or remove Impliciwait wait then script failed all time as loader get click instead of some other element.
The code i tried so far :
WebDriver driver = new FirefoxDriver();
System.out.println("Browser Opened");
driver.manage().window().maximize();
driver.get("https://www.rcontacts.in");
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
System.out.println("URL Opened");
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
driver.findElement(By.cssSelector(".ng-scope>a span[translate='login.register']")).click();
System.out.println("Register Link Clicked");
driver.findElement(By.name("userId")).sendKeys("9422307801");
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
driver.findElement(By.xpath("//button[#type='submit']")).click();
System.out.println("Mobile number entered");
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
Is there any solution that as soon as loader get removed it start performing actions ?
OR is there any way that I can wait until loader element get removed from DOM. Once removed then i can continue the further actions ?.
According to the docs,
WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times.
That's likely the cause of your issues. It's recommended to not use implicit waits. I would remove them and then add explicit waits as needed and see how that goes.
I took your code and rewrote it (below) and it's working every time for me.
String url = "https://www.rcontacts.in";
driver.navigate().to(url);
waitForLoader();
driver.findElement(By.cssSelector("span[translate='login.register']")).click();
waitForLoader();
driver.findElement(By.cssSelector("input[name='userId']")).sendKeys("9422307801");
driver.findElement(By.cssSelector("button[translate='common.btns.next']")).click();
The issue I was having at times was that many times the script was jumping ahead. I added code to waitForLoader() to wait for the loader to appear (be visible) and then disappear (be invisible). Once I did that, it worked 100% of the time.
public static void waitForLoader()
{
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfAllElementsLocatedBy(By.id("loading-bar")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
}
First and foremost, you have induced implicitlyWait() as follows:
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
As well as WebDriverWait() as follows:
new WebDriverWait(driver, 60).until(ExpectedConditions.invisibilityOfElementLocated(By.id("loading-bar")));
As per the documentation of Explicit and Implicit Waits it is clearly mentioned that:
Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.
Again, it seems changing the ExpectedConditions clause from invisibilityOfElementLocated(By.id("loading-bar") to elementToBeClickable(By.xpath("//span[contains(text(),'Register')]") gives me a success rate of 80%. Here is the effective code block on my Windows 8 box:
System.setProperty("webdriver.gecko.driver", "C:\\Utility\\BrowserDrivers\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://www.rcontacts.in");
System.out.println("URL Opened");
WebDriverWait wait = new WebDriverWait (driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//span[contains(text(),'Register')]")));
driver.findElement(By.xpath("//span[contains(text(),'Register')]")).click();
System.out.println("Register Link clicked");
Note: Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully to ensure that no dangling instance of geckodriver is present (through Task Manager) while you initiate the execution.

How to get PhantomJSDriver to work in selenium?

I am trying to use the PhantomJSDriver. The code below works with
FirefoxDriver but will not work with PhantomJSDriver. The error is:
[ERROR - 2016-02-12T16:02:47.717Z] WebElementLocator -
_handleLocateCommand - Element(s) NOT Found: GAVE UP. Search Stop Time: 1455292967683 org.openqa.selenium.NoSuchElementException: Error
Message => 'Unable to find element with id 'email''
Is there any clear guides on how to do this in Java, or can anyone get this working to login? I'm struggling to find some clarity on this topic.
I'm assuming the error is something to do with the browser being headless which therefore messes up with the paths but I have seen others using similar code and it works for them.
WebDriver driver = new PhantomJSDriver();
try {
System.out.println("Logging in to Facebook...");
driver.get("https://www.facebook.com/login");
System.out.println(driver.getTitle());
driver.findElement(By.id("email")).sendKeys("USERNAME");
driver.findElement(By.id("pass")).sendKeys("PASS");
driver.findElement(By.id("loginbutton")).click();
}
catch (Exception e) {
e.printStackTrace();
}
There's hundreds of similar questions to this one, e.g. this one. It's an issue that applies more or less equally to all browsers, and is a major cause of test instability.
Basically you're asking the Driver to find id="email" almost immediately (within milliseconds) after the page has been requested, and almost certainly before it has finished loading or that web element has been created in the DOM.
The solution is to wait until the element is ready before trying to send keys to it. See these examples. E.g.
System.out.println(driver.getTitle());
WebDriverWait wait = new WebDriverWait(driver, 10); // 10 secs max wait
wait.until(ExpectedConditions.presenceOfElementLocated( By.id("email") ));
driver.findElement(By.id("email")).sendKeys("USERNAME");
Once you know the DOM is loaded, there's no need to wait for the other elements.

Avoid the execution stop while browsing in Selenium WebDriver

I need help for this thing that's driving me crazy.
I want to check the browser url in and endless loop, waiting a little (Thread.Sleep) between a loop and another, to not overload the CPU. Then, if the browser url is what I need, I want to add/change/remove an element through Javascript before the page is fully loaded, otherwise the person who uses this could see the change. (I don't need help for the javascript part)
But there's a problem: it seems that in Selenium Webdriver when I navigate to a page (with .get(), .navigate().to() or also directly from the client) the execution is forced to stop until the page is loaded.
I tried to set a "fake" timeout, but (at least in Chrome) when it catches the TimeoutException, the page stops loading. I know that in Firefox there's an option for unstable loading, but I don't want to use it because my program isn't only for Firefox.
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().pageLoadTimeout(0, TimeUnit.MILLISECONDS); // Fake timeout
while (true) {
try {
// If the url (driver.getCurrentUrl()) is what I want, then execute javascript without needing that page is fully loaded
// ...
// ...
}
catch (TimeoutException e) {
// It ignores the Exception, but unfortunately the page stops loading.
}
Thread.sleep(500); // Then wait some time to not overload the cpu
}
}
I need to do this in Chrome, and if possible with Firefox and Internet Explorer. I'm programming in Java. Thanks in advance.
Selenium is designed to stop once the webpage is loaded into the browser so that it can proceed with execution.
In your case there are two options:
1) If the browser url will change automatically (ajax) at an arbitrary time, then just keep getting browser url until your condition satisfies.
while(currentURL.equals("Your Condition")){
currentURL = driver.getCurrentUrl();
Thread.sleep(2000);
}
2) If the browser needs to be refreshed use the refresh method in a loop until you get your desired url
while(currentURL.equals("Your Condition")){
driver.navigate().refresh();
currentURL =
Thread.sleep(2000);
}
As know, if user tried with driver.get("url");, selenium waits until page is loaded (may not be very long). so if you want to do some thing on navigate to URL without waiting total load time use below code instead of get or navigate
JavascriptExecutor js=(JavascriptExecutor)driver;
js.executeScript("window.open('http://seleniumtrainer.com/components/buttons/','_self');");
After this used
driver.findElement(By.id("button1")).click();
to click on button but i am getting no such element exception, so i am expecting its not waiting for page load. so times page loading very quick and click working fine.
i hope this will help you to figure it out your issue at start up. for loop i hope solution already provided.
Thanks

Difference between webdriver.get() and webdriver.navigate()

What is the difference between get() and navigate() methods?
Does any of this or maybe another method waits for page content to load?
What do I really need is something like Selenium 1.0's WaitForPageToLoad but for using via webdriver.
Any suggestions?
Navigating
The first thing you’ll want to do with WebDriver is navigate to a page. The normal way to do this is by calling get:
driver.get("http://www.google.com");
WebDriver will wait until the page has fully loaded (that is, the onload event has fired) before returning control to your test or script. It’s worth noting that if your page uses a lot of AJAX on load then WebDriver may not know when it has completely loaded. If you need to ensure such pages are fully loaded then you can use waits.
Navigation: History and Location
Earlier, we covered navigating to a page using the get command (driver.get("http://www.example.com")) As you’ve seen, WebDriver has a number of smaller, task-focused interfaces, and navigation is a useful task. Because loading a page is such a fundamental requirement, the method to do this lives on the main WebDriver interface, but it’s simply a synonym to:
driver.navigate().to("http://www.example.com");
To reiterate: navigate().to() and get() do exactly the same thing. One's just a lot easier to type than the other!
The navigate interface also exposes the ability to move backwards and forwards in your browser’s history:
driver.navigate().forward();
driver.navigate().back();
(Emphasis added)
They both seems to navigate to the given webpage and quoting #matt answer:
navigate().to() and get() do exactly the same thing.
Single-Page Applications are an exception to this.
The difference between these two methods comes not from their behavior, but from the behavior in the way the application works and how browser deal with it.
navigate().to() navigates to the page by changing the URL like doing forward/backward navigation.
Whereas, get() refreshes the page to changing the URL.
So, in cases where application domain changes, both the method behaves similarly. That is, page is refreshed in both the cases. But, in single-page applications, while navigate().to() do not refreshes the page, get() do.
Moreover, this is the reason browser history is getting lost when get() is used due to application being refreshed.
Originally answered: https://stackoverflow.com/a/33868976/3619412
driver.get() : It's used to go to the particular website , But it doesn't maintain the browser History and cookies so , we can't use forward and backward button , if we click on that , page will not get schedule
driver.navigate() : it's used to go to the particular website , but it maintains the browser history and cookies, so we can use forward and backward button to navigate between the pages during the coding of Testcase
Not sure it applies here also but in the case of protractor when using navigate().to(...) the history is being kept but when using get() it is lost.
One of my test was failing because I was using get() 2 times in a row and then doing a navigate().back(). Because the history was lost, when going back it went to the about page and an error was thrown:
Error: Error while waiting for Protractor to sync with the page: {}
driver.get() is used to navigate particular URL(website) and wait till page load.
driver.navigate() is used to navigate to particular URL and does not wait to page load. It maintains browser history or cookies to navigate back or forward.
As per the javadoc for get(), it is the synonym for Navigate.to()
View javadoc screenshot below:
Javadoc for get() says it all -
Load a new web page in the current browser window. This is done using
an HTTP GET operation, and the method will block until the load is
complete. This will follow redirects issued either by the server or as
a meta-redirect from within the returned HTML. Should a meta-redirect
"rest" for any duration of time, it is best to wait until this timeout
is over, since should the underlying page change whilst your test is
executing the results of future calls against this interface will be
against the freshly loaded page. Synonym for
org.openqa.selenium.WebDriver.Navigation.to(String).
navigate().to() and get() will work same when you use for the first time. When you use it more than once then using navigate().to() you can come to the previous page at any time whereas you can do the same using get().
Conclusion: navigate().to() holds the entire history of the current window and get() just reload the page and hold any history.
For what it's worth, from my IE9 testing, it looks like there's a difference for URLs that contain a hashbang (a single page app, in my case):
http://www.example.com#page
The driver.get("http://www.example.com#anotherpage") method is handled by the browser as a fragment identifier and JavaScript variables are retained from the previous URL.
While, the navigate().to("http://www.example.com#anotherpage") method is handled by the browser as a address/location/URL bar input and JavaScript variables are not retained from the previous URL.
There are some differences between webdriver.get() and webdriver.navigate() method.
get()
As per the API Docs get() method in the WebDriver interface extends the SearchContext and is defined as:
/**
* Load a new web page in the current browser window. This is done using an HTTP POST operation,
* and the method will block until the load is complete.
* This will follow redirects issued either by the server or as a meta-redirect from within the
* returned HTML.
* Synonym for {#link org.openqa.selenium.WebDriver.Navigation#to(String)}.
*/
void get(String url);
Usage:
driver.get("https://www.google.com/");
navigate()
On the other hand, navigate() is the abstraction which allows the WebDriver instance i.e. the driver to access the browser's history as well as to navigate to a given URL. The methods along with the usage are as follows:
to(java.lang.String url): Load a new web page in the current browser window.
driver.navigate().to("https://www.google.com/");
to(java.net.URL url): Overloaded version of to(String) that makes it easy to pass in a URL.
refresh(): Refresh the current page.
driver.navigate().refresh();
back(): Move back a single "item" in the browser's history.
driver.navigate().back();
forward(): Move a single "item" forward in the browser's history.
driver.navigate().forward();
driver.get("url") and driver.navigate( ).to("url") both are same/synonymous.
to("url") internally calling get("url") method. Please find the below image for reference.
Either of them does not store history - this is the wrong information that is available on most of the blogs/websites.
Below, statements 1, 2, and 3, 4 will do the same things i.e land in the given URL.
statemnt 1: driver.get("http://www.google.com");
statemnt 2: driver.navigate( ).to("http://www.amazon.in");
statemnt 3: driver.get("http://www.google.com");
statemnt 4: driver.get("http://www.amazon.in");
Only navigate() can do different things i.e. moving back, forward, etc. But not the to("url") method.
Otherwise you prob want the get method:
Load a new web page in the current browser window. This is done using an
HTTP GET operation, and the method will block until the load is complete.
Navigate allows you to work with browser history as far as i understand it.
Both perform the same function but driver.get(); seems more popular.
driver.navigate().to(); is best used when you are already in the middle of a script and you want to redirect from current URL to a new one. For the sake of differentiating your codes, you can use driver.get();to launch the first URL after opening a browser instance, albeit both will work either way.
CASE-1
In the below code I navigated to 3 different URLs and when the execution comes to navigate command, it navigated back to facebook home page.
public class FirefoxInvoke {
#Test
public static void browserInvoke()
{
System.setProperty("webdriver.gecko.driver", "gecko-driver-path");
WebDriver driver=new FirefoxDriver();
System.out.println("Before"+driver.getTitle());
driver.get("http://www.google.com");
driver.get("http://www.facebook.com");
driver.get("http://www.india.com");
driver.navigate().back();
driver.quit();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
browserInvoke();
}
}
CASE-2:
In below code, I have used navigate() instead of get(), but both the snippets(Case-1 and Case-2) are working exactly the same, just the case-2 execution time is less than of case-1
public class FirefoxInvoke {
#Test
public static void browserInvoke()
{
System.setProperty("webdriver.gecko.driver", "gecko-driver-path");
WebDriver driver=new FirefoxDriver();
System.out.println("Before"+driver.getTitle());
driver.navigate().to("http://www.google.com");
driver.navigate().to("http://www.facebook.com");
driver.navigate().to("http://www.india.com");
driver.navigate().back();
driver.quit();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
browserInvoke();
}
}
So the main difference between get() and navigate() is, both are
performing the same task but with the use of navigate() you can move
back() or forward() in your session's history.
navigate() is faster than get() because navigate() does not wait for
the page to load fully or completely.
driver.get(url) and navigate.to(url) both are used to go to particular web page. The key difference is that
driver.get(url): It does not maintain the browser history and cookies and wait till page fully loaded.
driver.navigate.to(url):It is also used to go to particular web page.it maintain browser history and cookies and does not wait till page fully loaded and have navigation between the pages back, forward and refresh.
To get a better understanding on it, one must see the architecture of Selenium WebDriver.
Just visit https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol
and search for "Navigate to a new URL." text. You will see both methods GET and POST.
Hence the conclusion given below:
driver.get() method internally sends Get request to Selenium Server Standalone. Whereas driver.navigate() method sends Post request to Selenium Server Standalone.

Categories