How to get PhantomJSDriver to work in selenium? - java

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.

Related

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

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.

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.

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

Appium's implicitlyWait does not work

I am using Appium to automate an iOS app but met a problem, is there anyone meet the same problem before?
Appium's implicitlyWait API seems to not work. I am using Java and JUnit to run the test, here is the line of code:
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
I have checked the debug info in the appium console, it looks correctly:
info: [debug] Set iOS implicit wait to 50000ms
My Environment:
Latest Appium 1.2.1, Java client library 1.6.1, Selenium Java language binding 2.42.2 and sample app 'UICatalog'provided by Sauce Lab.
Thanks in advance for the reply.
The code you have posted manages the timeout to wait for a maximum of 50 seconds. It doesn't make the driver wait 50 seconds. You can use the wait like:
driver.wait(); //this will wait a max of 50 seconds cuz you said so
If you ask me the proper way you would want to use waiting on Webdriver is:
WebDriverWait wait;
wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.id("blabla"));
The code above checks if blabla is clickable until that condition is proved or 60 seconds(stated above) passes the driver waits.
In Appium it is possible to set implicit way in this way:
Java code:
AppiumFieldDecorator decorator = new AppiumFieldDecorator(driver);
decorator.resetImplicitlyWaitTimeOut(50, TimeUnit.SECONDS);
PageFactory.initElements(decorator, this /* refers to current page object class*/);
Such timeout will work for the whole time.
It is not possible (at least I don't know) to change it.
As when web drivers are used you can do this with:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
// some actions for which you don't want to wait implicitly
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
Try this:
public static void WaitForElementPresent1(String locator, int timeout)
{
WebDriverWait wait = new WebDriverWait(driver, timeout);
try{
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(locator)));
} catch (Exception e){
e.printStackTrace();
}
}
If you are using PageFactory model, you can specify the implicit wait with initElements() method as given below -
PageFactory.initElements(new AppiumFieldDecorator(driver, 10, TimeUnit.SECONDS), this);
I have tried this with Appium 1.6 and it works fine.
The new way of setting the implicit time out is using the code
AppiumFieldDecorator decorator = new AppiumFieldDecorator(mobDriver);
decorator.DEFAULT_IMPLICITLY_WAIT_TIMEOUT = longValue;
decorator.DEFAULT_TIMEUNIT = TimeUnit.TimeUnit ;
Hope this helps

How do I set the selenium webdriver get timeout?

When I am using a proxy in webdriver like FirefoxDriver, if the proxy is bad then the get method will block forever. I set some timeout parameters, but this did not work out.
This is my code:
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("general.useragent.override", ua);
Proxy p = new Proxy();
p.setHttpProxy(proxy);
profile.setProxyPreferences(p);
profile.setEnableNativeEvents(true);
// create a driver
WebDriver driver = new FirefoxDriver(profile);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.manage().timeouts().setScriptTimeout(30, TimeUnit.SECONDS);
driver.get("www.sina.com.cn")
The call to driver.get will block for ever, but I want it to wait for 30 seconds and if the page is not loaded then throw an exception.
Try this:
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
The timeouts() methods are not implemented in some drivers and are very unreliable in general.
I use a separate thread for the timeouts (passing the url to access as the thread name):
Thread t = new Thread(new Runnable() {
public void run() {
driver.get(Thread.currentThread().getName());
}
}, url);
t.start();
try {
t.join(YOUR_TIMEOUT_HERE_IN_MS);
} catch (InterruptedException e) { // ignore
}
if (t.isAlive()) { // Thread still alive, we need to abort
logger.warning("Timeout on loading page " + url);
t.interrupt();
}
This seems to work most of the time, however it might happen that the driver is really stuck and any subsequent call to driver will be blocked (I experience that with Chrome driver on Windows). Even something as innocuous as a driver.findElements() call could end up being blocked. Unfortunately I have no solutions for blocked drivers.
try
driver.executeScript("window.location.href='http://www.sina.com.cn'")
If you have set pageLoadStrategy to none, this statement will return immediately.
And after that , you can add a WebDriverWait with timeout to check if the page title or any element is ok.
Hope this will help you.
I had the same problem and thanks to this forum and some other found the answer.
Initially I also thought of separate thread but it complicates the code a bit. So I tried to find an answer that aligns with my principle "elegance and simplicity".
Please have a look at such forum:
https://sqa.stackexchange.com/questions/2606/what-is-seleniums-default-timeout-for-page-loading
#
SOLUTION:
In the code, before the line with 'get' method you can use for example:
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
#
One thing is that it throws timeoutException so you have to encapsulate it in the try catch block or wrap in some method.
I haven't found the getter for the pageLoadTimeout so I don't know what is the default value, but probably very high since my script was frozen for many hours and nothing moved forward.
#
NOTICE:
'pageLoadTimeout' is NOT implemented for Chrome driver and thus causes exception. I saw by users comments that there are plans to make it.
You can set the timeout on the HTTP Client like this
int connectionTimeout=5000;
int socketTimeout=15000;
ApacheHttpClient.Factory clientFactory = new ApacheHttpClient.Factory(new HttpClientFactory(connectionTimeout, socketTimeout));
HttpCommandExecutor executor =
new HttpCommandExecutor(new HashMap<String, CommandInfo>(), new URL(seleniumServerUrl), clientFactory);
RemoteWebDriver driver = new RemoteWebDriver(executor, capabilities);
The solution of driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS) will work on the pages with synch loading. This does not solve, however, the problem on pages loading stuff in async, then the tests will fail all the time if we set the pageLoadTimeOut.
I find that the timeout calls are not reliable enough in real life, particularly for internet explorer , however the following solutions may be of help:
You can timeout the complete test by using #Test(timeout=10000) in the junit test that you are running the selenium process from. This will free up the main thread for executing the other tests, instead of blocking up the whole show. However even this does not work at times.
Anyway by timing out you do not intend to salvage the test case, because timing out even a single operation might leave the entire test sequence in inconsistent state. You might just want to proceed with the other testcases without blocking (or perhaps retry the same test again). In such a case a fool-proof method would be to write a poller that polls processes of Webdriver (eg. IEDriverServer.exe, Phantomjs.exe) running for more than say 10 min and kill them. An example could be found at Automatically identify (and kill) processes with long processing time
Used below code in similar situation
driver.manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS);
and embedded driver.get code in a try catch, which solved the issue of loading pages which were taking more than 1 minute.

Categories