0

I wrote a simple method to check to see if a WebElement is enabled and put this method in my test case Super Object:

protected boolean isElementEnabled(By by) {
    // Temporarily set the implicit timeout to zero
    int originalTimeout = Integer.parseInt(System.getProperty(
            "com.brainshark.uitests.timeout", "120"));
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
    // Check to see if there are any elements in the found list
    List<WebElement> elements = driver.findElements(by);
    boolean isEnabled = (elements.size() == 1)
            && elements.get(0).isEnabled();
    // Return to the original implicit timeout value
    driver.manage().timeouts()
            .implicitlyWait(originalTimeout, TimeUnit.SECONDS);
    return isEnabled;
}

I have been using it quite a bit without issue, but suddenly I am faced with a repeatable instance where this method throws an InvalidElementStateException:

org.openqa.selenium.InvalidElementStateException: findElements execution failed; SYNTAX_ERR: DOM Exception 12 (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 13 milliseconds Build info: version: '2.23.1', revision: 'unknown', time: '2012-06-08 12:33:29' System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_05' Driver info: driver.version: RemoteWebDriver Session ID: ed1a9cbb238fa4dfb616ad81e7f60141

It appears that the failure depends on the locator that I'm searching for. Is there something inherently wrong with this locator?

final By AdministrationButton = By
            .cssSelector("div#top-nav a[href~=CorpAdmin/DisplayInformation]");

To verify, the above locator is trying to locate the anchor element with an href attribute that contains "CorpAdmin/DisplayInformation" which is a descendant of a div with id=top-nav. Shouldn't a CSS Locator like the one I'm using work for ChromeDriver? Does anyone know why methods like findElements throw InvalidElementStateExceptions? Thanks in advance!

Addendum: Further investigating is showing that the method is failing only after I navigate from one page to another via a different method. It feels like something is getting stale or referring to elements that no longer exist or something to that effect. However, I can't fathom what that is; the same driver object is made available to the test cases and page objects, and is being employed every time isElementEnabled is called. No WebElements from previous pages are being cached or referenced. Is there something I need to do with my driver to alert it that the page has changed?

Addendum 2: The plot thickens. Now I'm not so sure about that previous addendum. Things still fail after navigating to a new page, but I'm not certain if that locator is the problem or not. I tried peppering my code with calls like this:

debug("Attempt 3...");
things = getDriver().findElements(By.cssSelector("div a"));
debug("Attempt 3 found " + things.size() + " things!");

These calls succeed until I navigate away from the page I started on. They locate 35 elements on the page matching the simple locator. However, once I navigate to the new page I get a new Exception:

org.openqa.selenium.WebDriverException: findElements returned invalid value: "[{\"ELEMENT\": \":wdc:1347370086846\"}, {\"ELEMENT\": \":wdc:1347370086847\"}, {\"ELEMENT\": \":wdc:1347370086848\"}, {\"ELEMENT\": \":wdc:1347370086849\"}, {\"ELEMENT\": \":wdc:1347370086850\"}, {\"ELEMENT\": \":wdc:1347370086851\"}, {\"ELEMENT\": \":wdc:1347370086852\"}, {\"ELEMENT\": \":wdc:1347370086853\"}, {\"ELEMENT\": \":wdc:1347370086854\"}, {\"ELEMENT\": \":wdc:1347370086855\"}, {\"ELEMENT\": \":wdc:1347370086856\"}, {\"ELEMENT\": \":wdc:1347370086857\"}, {\"ELEMENT\": \":wdc:1347370086858\"}, {\"ELEMENT\": \":wdc:1347370086859\"}, {\"ELEMENT\": \":wdc:1347370086860\"}, {\"ELEMENT\": \":wdc:1347370086861\"}, {\"ELEMENT\": \":wdc:1347370086862\"}, {\"ELEMENT\": \":wdc:1347370086863\"}, {\"ELEMENT\": \":wdc:1347370086864\"}, {\"ELEMENT\": \":wdc:1347370086865\"}, {\"ELEMENT\": \":wdc:1347370086866\"}, {\"ELEMENT\": \":wdc:1347370086867\"}, {\"ELEMENT\": \":wdc:1347370086868\"}, {\"ELEMENT\": \":wdc:1347370086869\"}]" (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 9 milliseconds Build info: version: '2.23.1', revision: 'unknown', time: '2012-06-08 12:33:29' System info: os.name: 'Windows 7', os.arch: 'amd64', os.version: '6.1', java.version: '1.7.0_05' Driver info: driver.version: RemoteWebDriver Session ID: 174adf3205213984172556afa718f6a1

Is that how Selenium represents WebElements? I imagine those are just references to the objects themselves. There are only 26 of them, rather than the 35 that were previously returned (since we are on a different page, this may be the correct number). Unsure why something is invalid or what though. If I instead call isElementEnabled on the locator for my AdministrationButton above, I get the InvalidElementSateException as before.

Prasad
  • 472
  • 5
  • 15
James Martineau
  • 951
  • 1
  • 13
  • 29
  • 1
    Does clicking that anchor perform any kind of refresh or postback? Also what version of both Chrome & ChromeDriver do you have>? – Arran Sep 11 '12 at 13:33
  • Clicking the AdministrationButton anchor would indeed refresh the page, either navigating to a different page or simply refreshing if you were already there, I guess. That button/anchor is never actually being clicked, however. I'm just trying to find out if it's there, since its presence indicates roughly where in the site I am. It's very odd; there definitely seems to be something about either the locator or the page itself that is making Selenium angry. I wish there were more information about precisely what and why. I am using Chrome 21.0.1180.89 m and ChromeDriver 2.23.1. – James Martineau Sep 11 '12 at 14:05
  • 1
    You're getting a DOM exception - have you tried running the page that you're testing through a validator? – jimaltieri Sep 11 '12 at 16:34
  • @jimaltieri I have not yet validated the page in question - I'm somewhat new to web UI automation so I'll have to ask around my company for the best way to do that. But the overall point is very interesting to me, and is something I had been wondering. Basically, this DOM Exception could be getting thrown not because there's anything wrong with my code or my locator, but because the page employs invalid CSS and the WebDriver is unable to properly search it, correct? – James Martineau Sep 11 '12 at 18:00
  • @rironin It's certainly possible. Run the page through something like http://validator.w3.org/ – jimaltieri Sep 12 '12 at 15:19

2 Answers2

2

1)first point. frankly speaking i don't like your method isElementEnabled is organized. to get to know whether selenium is able to manipulate with your localized element try this:

public boolean isElementPresent(By locatorKey) {
        try {
            driver.findElement(locatorKey);
            return true;
        } catch (org.openqa.selenium.NoSuchElementException e) {
            return false;
        }
    }

driver.findElement(By.cssSelector(....)).isEnabled();
driver.findElement(By.cssSelector(....)).isDisplayed()

But before using this methods i recommend you to use fluent wait. Fluent wait returns you found web element by locator (note:if something fails on fluent wait then you'd better to pay attention to your xpath or cssselector of the neded element) :

 public WebElement fluentWait(final By locator){
        Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                .withTimeout(30, TimeUnit.SECONDS)
                .pollingEvery(5, TimeUnit.SECONDS)
                .ignoring(NoSuchElementException.class);

        WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
            public WebElement apply(WebDriver driver) {
                        return driver.findElement(locator);
                }
                }
);
                           return  foo;              }     ;

About fluent wait i recommend you to read here

And concerning your way of finding cssSelector frankly speaking i don't like it either. Instead of "div#top-nav a[href~=CorpAdmin/DisplayInformation]" try better this div[id='top'] nav a[href~='CorpAdmin/DisplayInformation'] And always check your localized elements with css or xPAth (e.g. in firepath, firefox addon to firebug). See the picture below: firepath localizing

Hope this somehow helps you.

eugene.polschikov
  • 7,254
  • 2
  • 31
  • 44
  • 1
    Thanks for the comments. I am aware of the possibility of calling a find method and catching the possible Exception as a test for existence, but the method I am currently employing is actually recommended by the [Selenium API](http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/WebDriver.html#findElement(org.openqa.selenium.By)): **"findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead."** I am also familiar with fluent waits and have used them elsewhere in the project. – James Martineau Sep 11 '12 at 17:10
  • As for the locator business, I thought that `div#top-nav` was functionally equivalent to `div[id='top-nav']` - is that not the case? Also, wouldn't your suggested version look for an anchor element that's a descendant of a nav element that's a descendant of a div element? That's not the structure of my page. The div element has `id=top-nav`. There is no nav element. – James Martineau Sep 11 '12 at 17:13
  • when I check my css locators in firepath. css like div#top-nav sometimes fail, so I prefer to use div[id='top-nav'] instead of it. findElement and assert zero length is a good approach . – eugene.polschikov Sep 11 '12 at 17:16
  • Thanks for the tip about firepath, I had wanted a plugin that would let me test my locators and highlight them for me like the Selenium IDE did. I'm very sad to hear that `#blah` isn't as reliable as `[id='blah']`... now I feel like I have to assume so many things will just potentially not work. Argh! – James Martineau Sep 11 '12 at 17:58
  • By the way, I've come across with the similar problem with such exception. – eugene.polschikov Sep 12 '12 at 09:09
1

By the way, I've come across with the similar problem with such exception. Selenium webcrawling combo box So this kind of problem means that you've come across with the element which selenium is unable to interact with(i.e invisible, disables and so on). So in theses cases js helps me (in clicking elements or getting the text of elements). I like the way js interacts with elements which are invisible (disabled). And IMHO we don't need element visibility (or enabled/disabled) verification using js cheating approach)

public void jsClickOnElement(String cssSelector){
        JavascriptExecutor js = (JavascriptExecutor) driver;
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("var x = $(\'"+cssSelector+"\');");
        stringBuilder.append("x.click();");
        js.executeScript(stringBuilder.toString());

    }
Community
  • 1
  • 1
eugene.polschikov
  • 7,254
  • 2
  • 31
  • 44