In certain unknown situations selenium does not detect that a page has loaded when using the open method. I am using the Java API. For example (This code will not produce this error. I don't know of an externally visible page that will.):
Selenium browser = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com");
browser.start();
browser.open("http://www.google.com/webhp?hl=en");
browser.type("q", "hello world");
When the error occurs, the call to 'open' times out, even though you can clearly see that the page has loaded successfully before the timeout occurs. Increasing the timeout does not help. The call to 'type' never occurs, no progress is made.
How do you get selenium to recognize that the page has loaded when this error occurs?
I faced this problem quite recently.
All JS-based solutions didn't quite fit ICEFaces 2.x + Selenium 2.x/Webdriver combination I have.
What I did and what worked for me is the following:
In the corner of the screen, there's connection activity indicator.
<ice:outputConnectionStatus id="connectStat"
showPopupOnDisconnect="true"/>
In my Java unit test, I wait until its 'idle' image comes back again:
private void waitForAjax() throws InterruptedException {
for (int second = 0;; second++) {
if (second >= 60) fail("timeout");
try {
if ("visibility: visible;".equals(
selenium.getAttribute("top_right_form:connectStat:connection-idle#style"))) {
break;
}
} catch (Exception e) {
}
Thread.sleep(1000);
}
}
You can disable rendering of this indicator in production build, if showing it at the page is unnecessary, or use empty 1x1 gifs as its images.
Works 100% (with popups, pushed messages etc.) and relieves you from the hell of specifying waitForElement(...) for each element separately.
Hope this helps someone.
Maybe this will help you....
Consider the following method is in page called Functions.java
public static void waitForPageLoaded(WebDriver driver) {
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
WebDriverWait wait = new WebDriverWait(driver,30);
try {
wait.until(expectation);
} catch(Throwable error) {
Assert.assertFalse(true, "Timeout waiting for Page Load Request to complete.");
}
}
And you can call this method into your function. Since it is a static method, you can directly call with the class name.
public class Test(){
WebDriver driver;
#Test
public void testing(){
driver = new FirefoxDriver();
driver.get("http://www.gmail.com");
Functions.waitForPageLoaded(driver);
}
}
When I do Selenium testing, I wait to see if a certain element is visible (waitForVisible), then I do my action. I usually try to use an element after the one I'm typing in.
Using 'openAndWait' in place of 'open' will do the trick.
From the website:
Many Actions can be called with the "AndWait" suffix, e.g. "clickAndWait". This suffix tells Selenium that the action will cause the browser to make a call to the server, and that Selenium should wait for a new page to load.
Enabling the 'multiWindow' feature solved the issue, though I am not clear why.
SeleniumServer(int port, boolean slowResources, boolean multiWindow)
SeleniumServer server = new SeleniumServer(4444, false, true);
Any clarification would be helpful.
I've run into similar issues when using Selenium to test an application with iFrames. Basically, it seemed that once the primary page (the page containing the iframes) was loaded, Selenium was unable to determine when the iframe content had finished loading.
From looking at the source for the link you're trying to load, it looks like there's some Javascript that's creating additional page elements once the page has loaded. I can't be sure, but it's possible that this is what's causing the problem since it seems similar to the situation that I've encountered above.
Do you get the same sort of errors loading a static page? (ie, something with straight html)
If you're unable to get a better answer, try the selenium forums, they're usually quite active and the Selenium devs do respond to good questions.
http://clearspace.openqa.org/community/selenium_remote_control
Also, if you haven't already tried it, add a call to browser.WaitForPageToLoad("15000") after the call to open. I've found that doing this after every page transition makes my tests a little more solid, even though it shouldn't technically be required. (When Selenium detects that the page actually has loaded, it continues, so the actual timeout variable isn't really a concern..
Not a perfect solution, but I am using this method
$t1 = time(); // current timestamp
$this->selenium->waitForPageToLoad(30);
$t2 = time();
if ($t2 - $t1 >= 28) {
// page was not loaded
}
So, it is kind of checking if the page was not loaded during the specified time, so it is not loaded.
another idea is to modify AJAX API (to add some text after AJAX actions).
After ajax action was finished, before return, set invisible field to TRUE, selenium will find it and read as green-light
in html:
<input type='hidden' id="greenlight">
in selenium
if(driver.findElement(By.id("greenlight")).getAttr("value").equals("TRUE")){
// do something after page loading
}
If you page has no AJAX, try to seek footer of page (I also use Junit fail(""), you may use System.err.println() instead):
element.click();
int timeout =120;
// one loop = 0.5 sec, co it will be one minute
WebElement myFooter = null;
for(int i=0; i<timeout; i++){
myFooter = driver.findElement(By.id("footer"));
if(myFooter!= null){
break;
}
else{
timeout--;
}
}
if(timeout==0 && myFooter == null){
fail("ERROR! PAGE TIMEOUT");
}
Related
I have several tests that run with Selenium and HtmlUnitDriver. Sometimes when I run them and want to click on an element or read text, the elements can not be found. Every time a Exception is thrown I save the Code of the Page for debugging purposes. But when I check the Code, the element is there and when I rerun the test everything works fine.
My guess is that the page was not completely loaded when I try to access the element.
So I would like to wait until Selenium has finished loading the page before I try to access elements.
I fond two ways to achieve it:
Execute Javascript (e.g. window.initComplete) and wait for the result to be true. The problem: In Selenium I have to have an instance of JavascriptExecuter but HtmlUnitDriver is not derived from that class and I cannot switch to FirefoxDriver (which implements the JavascriptExecuter interface) because we are running the tests headless.
Wait for the last element on the page to load
The problem with this approach is that the page is based on our framework and if that changes and suddenly there are different elements on the bottom of the page I have to adapt every test.
Any suggestions on how to approach the problem?
You can create a custom ExpectedCondition:
public static ExpectedCondition<Boolean> waitForLoad() {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver driver) {
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
};
}
I am writing some automated tests using Fluentlenium and PhantomJS. I am having trouble accessing the id "#title". The test I have written is as follows:
#Test
public void testCreateButton() {
startAppWithCallback(new F.Callback<TestBrowser>() {
public void invoke(TestBrowser browser) throws InterruptedException {
CalendarPage calendarPage = browser.createPage(CalendarPage.class);
calendarPage.withDefaultUrl(BASE_URL);
calendarPage.go();
calendarPage.selectCreateButton();
calendarPage.typeTitle("Java Fundamentals");
browser.await().atMost(3, TimeUnit.SECONDS);
}
});
}
The test is running, and seems to be able to select the Create button, which should then open up a modal window, but for some reason it is having trouble seeing the id on this modal. The error message that I get is as follows:
org.openqa.selenium.NoSuchElementException: No element is displayed or enabled. Can't set a new value.
Is there something I am not doing when it comes to accessing the id on the modal window? Any help at all would be much appreciated.
Usually modal windows take some time to attach to the DOM of the page you are accessing. Though you have added 3 seconds to wait for the element to appear/ attach to the DOM but the time is not sufficient. I would not recommend to increase the timeout but would recommend to wait until for the element to appear and then move forward. for e.g. you could do following thing to wait for an element to appear on the page instead of waiting statically:
FluentWaitMatcher matcher = page.await().atMost(, TimeUnit.SECONDS).until(findPattern);
I'm facing an issue when application I'm testing is opening a second level popup (I mean, a popup that rises another popup). I'm using Selenium for Java, version 2.42.2, with IE Driver.
My code currently manages all other flows and single pop ups windows, but when a second level popup appears my webdriver object gets irresponsive and just stuck in any method that try to get invoked. When this happens, I need to manually close the popup window and then driver method continues the execution of invoked method.
Maybe it worth mentioning, if I call the second popup from the main page (not from another popup) I am able to manage it without problems, so the problem seems to be related with the number of nested windows more than a specific problem for the page.
Take a look on below code:
String url = "/example.jsp"
int counter = 0;
boolean windowDetected = false;
// Waiting until page with given url gets detected
// It tries 10 times before it continues
while (counter++ < 10 && !windowDetected) {
waitForSeconds(1); // Just invokes Thread.sleep method,
System.out.println("before getting handlers, iteration " + counter + " of 10");
Set<String> handlers = driver.getWindowHandles();
System.out.println("after getting handlers, number of handlers: " + handlers.size());
for (String handler : handlers) {
try {
System.out.println("Moving to " + handler);
driver.switchTo().window(handler);
}
catch (NoSuchWindowException e) {
System.out.println("Window not found, it probably redirected to a different window");
break;
}
if (driver.getCurrentUrl().contains(url)) {
windowDetected = true;
waitForPageLoading(); // It just verify current page status to be completed
break;
}
}
}
I am able to position properly the driver in specific window with above code in other application pages, but when having the second level popup it just hangs on line Set handlers = driver.getWindowHandles(); that is the first method called on driver object after popup appeared. Similarly, if I had called another driver method like driver.getPageSource() the same would have happened in that method.
I am not able to change application structure (my scope is only for testing it), so doing changes in web application code is not an option for me now. I have read on different options like trying Robot class, but I think it will be difficult to implement with more complex pages and difficult to maintain.
Any idea of how can I solve this issue? Many thanks in advance.
Best regards,
Alberto.
After taking a look on IEDriverServer changelog, moving to a newer version of this driver solved the issue. Previous was 2.24.2, and now using 2.44. A slightly different behavior but that accomplishes what I wanted
What I am trying to accomplish is browsing to a page, waiting for something to load and then taking and saving a screenshot.
The code I already have is
WebDriver driver = new FirefoxDriver();
driver.get("http://www.site.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
try {
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("/home/Desktop/image.png"));
} catch (Exception e) {
e.printStackTrace();
}
driver.close();
The reason I need to wait, even if the page is loaded is because it'll be loaded but on the site the content I'd like to take a picture of loads after a few seconds. For some reason the page is not waiting, is there another method that I can use to get the driver/page to wait for X amount of seconds?
You can locate an element that loads after the initial page loads and then make Selenium wait until that element is found.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ID")));
That wouldnt really be a selenium specific thing. You just want java to sleep for a bit after loading the page but before taking the screenshot.
Thread.sleep(4000);
put that after your driver.get statement.
If you want to delay a certain number of seconds, rather than to respond as soon as possible, here is a function for pause similar to what selenium IDE offers:
public void pause(Integer milliseconds){
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
source
The most simple of all.
Just try this and forget rest! The equivalent of this code can be used in any language.
I am writing this in python.
import time
time.sleep(2)
this will make the compiler go to sleep for 2 seconds.
Just in case it will help somebody, you should always try to avoid implicit waits and especially Thread#sleep as much as you can. If you do Thread.sleep(10), your code will always wait for 10 seconds even in case your page is ready after 1 sec. So this can slow your tests substantially if you use this often.
Better way is to use ExplicitWaits which you means you will wait exactly as long as some action happens or some element gets rendered on the page. So in your case, I would use explicit wait to check whether is everything loaded and then take a screenshot.
const { By, until } = require('selenium-webdriver');
this.wait = async function (amount: number) {
try {
await this.driver.wait(
until.elementLocated(By.css('[data-test-id="does-not-exist"]')),
amount,
'Looking for element'
);
} catch (e) {
console.log('waiting')
}
We look for a css identifier that isn't there for x amount of seconds. This is typescript btw. This would be a method on some relevant class, or a function by itself. Use it like this
const button = await this.findByCSSSelector('[data-test-id="get-quote-button"]')
const actions = this.driver.actions({ bridge: true });
await actions.move({origin: button }).perform();
// Small pause to observe animation is working correctly in all browsers
await this.wait(700)
const carat = await this.findByCSSSelector('[data-test-id="carat"]');
This waits for .7 of a second so that you can see that whatever animation is working in your functional tests.
I was trying to click a button on my mobile web app, using selenium web driver. The button is located, the text over the button can be derived and even the click event is performing well. But the navigation doesn't occur.
I tried with Click() method, sendKeys() method and also with script executor. But couldn't process further on.
CODE:
public class TestWeb
{
WebDriver driver;
private Selenium selenium;
#Before
public void setUp() throws Exception {
driver = new IPhoneDriver();
driver.get("http://10.5.95.25/mobilebanking");
}
#Test
public void TC() throws Exception {
System.out.println("page 1");
Thread.sleep(5000);
WebElement editbtn1 = driver.findElement(By.id("ext-comp-1018"));
String s1 = editbtn1.getText();
System.out.println(s1);
editbtn1.click();
editbtn1.sendKeys(Keys.ENTER);
((JavascriptExecutor)driver).executeScript("arguments[0].click;", editbtn1);
System.out.println("ok");
}
#After
public void tearDown() throws Exception {
System.out.println("*******Execution Over***********");
}
}
I tried click, sendKeys and ScriptExecutor separately and also combined. It is executing without any error but the navigation doesn't occur.
Does anybody can help me with some other ways to perform click function on the button?
Ram
This may not be your issue but I noticed "ext-comp-" and guess you are using extjs.
I'm using GXT and while finding by id worked for many things, on some submit buttons it didn't.
I had to use firebug in firefox to locate the element and copy the xpath.
Then I could click the element by
driver.findElement(By.xpath("//div[#id='LOGIN_SUBMIT']/div/table/tbody/tr[2]/td[2]/div/div/table/tbody/tr/td/div")).click(); // worked
It was failing silently for me too. My submit button has the id of LOGIN_SUBMIT so I don't know why the following failed but ....
driver.findElement(By.id("LOGIN_SUBMIT")).click();//failed
Edit:
Here is an exact example (case 1 of 2):
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//div[#id='gwt-debug-LOGIN_SUBMIT']")));
//wait.until(ExpectedConditions.elementToBeClickable((By.id("gwt-debug-LOGIN_SUBMIT")))); <!-- id works as well
OK so the element is found. It will timeout and throw an exception if it is not.
Still, the following fails (under firefox, works with chrome) with no error and the page does not navigate.
driver.findElement(By.xpath("//div[#id='gwt-debug-LOGIN_SUBMIT']")).click();
//driver.findElement(By.id("gwt-debug-LOGIN_SUBMIT")).click(); <-- fails too
What I have to do is:
driver.findElement(By.xpath("//div[#id='gwt-debug-LOGIN_SUBMIT']/div/table/tbody/tr[2]/td[2]/div/div/table/tbody/tr/td/div")).click();
So my experience was that even if I found the element with xpath, clicking failed unless I used a complete xpath.
Here is another exact example (case 2 of 2):
I can find an element like so:
WebElement we = driver.findElement(By.xpath("//*[#id=\"text" + i + "\"]"));
I know I have found it because I can see the text via:
we.getText();
Still selecting by the path I found it fails.
//get outta town man the following fails
driver.findElement(By.xpath("//*[#id=\"text" + i + "\"]")).click();
In this case there is not more explicit xpath to try as in case 1
What I had to do was use css:
//bingo baby works fine
driver.findElement(By.cssSelector("div#text" + i + ".myChoices")).click();
Actually, I obtained the css path via firebug than shortened it.
//this is what I recieved
html.ext-strict body.ext-gecko div#x-auto-0.x-component div#x-auto-1.x-component div#x-auto-3..myBlank div#choicePanel1.myBlank div.x-box-inner div#text3.myChoices //text3 is the id of the element I wanted to select
Whether or not you can figure out your needed xpaths and css selectors, I don't know, but I believe I experienced exactly what you did.