9

I am using Selenium 2 2.16 build. I've been running into problems where I get a variable response to a click() call, where sometimes the click activates the behaviour behind the element (new page loads) and sometimes it does not. As click() doesn't return anything, I can't trap for those occurences where the driver doesn't go to a new page.

Here's a code snippet :

// Find the User Profile Button
def userProfileButton = driver.findElement(By.className("user"))
assert userProfileButton.isEnabled()
assert userProfileButton.getText() == "Facility Administrator"
userProfileButton.findElement(By.tagName("a")).click()

// Check User Profile page loads
def userProfilePanel = driver.findElement(By.id("profile-panel"))
.... do some tests on the userProfilePanel

So I am locating the link, checking it is enabled and has the right name, then clicking on it. The next step will sometimes time out (I have the driver set to wait up to 10 seconds before timing out), as the new page is not loaded. Other times, it works fine.

The page in question is JavaScript based and using Ext JS to do the rendering of the page.

This is not the only case I have where the click() is unreliable. Do other people have similar problems?

I'd prefer not to use the work around I've seen which is to call sendkeys(Enter), as I'd like to simulate the real user clicks and data entry if at all possible.

2
  • I compared 2.16 to 2.14 and 2.12 and I'm pretty well convinced that the .click() method changes have broken something. Only sendkeys() in 2.16 seems to let me press buttons and links, and for the items which I need to just click on (sending a enter key in the web site itself) these are not working as expected, with the click being a null-op.
    – theCesspit
    Jan 10, 2012 at 22:33
  • 1
    2.17 has a fix for the problem I was seeing 2.16 : code.google.com/p/selenium/issues/detail?id=3144 Thanks all for your help.
    – theCesspit
    Jan 20, 2012 at 17:39

5 Answers 5

5

Phrase "sometimes works sometimes not" often means that Selenium tried to make an action when that action was unavailable at that time (the easiest method to check is to make long pauses before each action).

In this case I recommend for you to make your own custom method WaitWhileProcessing which commands WebDriver to wait until full page is rendered. How you write that on your custom method depends on your web applications (sometimes you only need to wait until specific page element is loaded).

3
  • I've done some further investigation, and tried to make sure the elements is actually there, and has the link I am clicking on (by checking the href attribue of the element). This returns the correct values, but still the click does not work.
    – theCesspit
    Jan 6, 2012 at 22:21
  • @theCesspit did you try time.sleep(10) method before each action (while debugging)? However there appears exist similar issue posted on SO. Jan 7, 2012 at 11:31
  • I've put in a time out in places, and this doesn't seem to resolve it. I've actually checked that the href element is available on the element before sending the click. In another section of code with no javascript, the click on a button element completely fails every time (only a sendkeys return code works).
    – theCesspit
    Jan 7, 2012 at 17:50
2

As long as you make sure the element you want to click is actually ready, then it will work reliably. There are ways to find elements without throwing exceptions by using try-catch conditions inside of loops. For example, this method I wrote (which can be simplified depending on what you use if for) will return a WebElement and it makes sure that it's clickable before returning it to you:

/**
 * Example of using finally to "ignore" exceptions from Selenium
 *  findElement() method.
 */
public static WebElement getElementByLocator( final By locator ) {
  driver.manage().timeouts().implicitlyWait( 15, TimeUnit.SECONDS );
  WebElement we = null;
  int tries = 0;
  while ( tries < 4 ) {
    try {
      we = driver.findElement( locator );
      break;
    } catch ( StaleElementReferenceException e ) {                      
      LOGGER.info( "Ignoring stale element exception.");
    } finally { // use finally block to totally ignore exception block
      tries += 1;
    }
  }
  driver.manage().timeouts().implicitlyWait( DEFAULT_IMPLICIT_WAIT, TimeUnit.SECONDS );
  return we;
}

NOTE: You can also improve this method by altering it to use the FluentWait class or the Wait class to ignore exceptions rather than handling them explicity (like you see above). I recommend this, but if you prefer, you can do it organically like I show above.

1

I am not an expert with Selenium but here are some techniques I used for this problem (using Java):

  • Using the Actions class: builder.clickAndHold('your web element') method then the builder.release('your web element'). This gives some time between the click and release so the click action would take effect

  • Clicking and then making sure the expected results was achieved if not repeat again this section of code in a while loop.

  • There are some suggestions to click the element twice in a try catch block and catch the NoSuchElementException and do whatever required then.

1
  • Pt.1 is a good tipp; the two other points do not look right for testing, though.
    – nibra
    May 16, 2013 at 18:03
0

I'm not sure what language API you are using, but I solved many of loading troubles in a javascript app using the WaitForWait class. You may have to do some translation work, but in the .NET i built a factory method to generate WaitForWait classes with a totalWaitTimeout which will throw an exception if reached and waitInterval which is time the driver will wait until it checks for the element again.

public static class WaitFactory
{
    public const int TotalWaitSeconds = 10;
    public const int WaitIntervalMiliseconds = 50;

    public static WebDriverWait GetWait(IWebDriver driver)
    {
        var clock = new SystemClock();
        var totalWaitTimeout = new TimeSpan(0, 0, TotalWaitSeconds);
        var waitInterval = new TimeSpan(0, 0, 0, 0, WaitIntervalMiliseconds);
        return new WebDriverWait(clock, driver, totalWaitTimeout, waitInterval);
    }
}

And then write a function like this:

public void WaitForPanelToAppear(IWebDriver driver)
{
    var wait = WaitFactory.GetWait(driver);
    wait.Until(webDriver => webDriver.findElement(By.id("profile-panel")).Displayed);
}

Which you should call after clicking the button to generate a page change and before doing stuff with the element you are waiting for to load.

0

It works fine with the latest version of Firefox(v29), but for Chrome it creates problems and sometimes you have to manually click on the page link to continue the code execution. Element Click on menus and sub-menus only works(in Chrome v34.0) if your mouse pointer is not over the browser on which code is running. Place the pointer to else where away from the browser or if feasible use another screen. Worked for me!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.