9

I am using Selenium 3.4 with Java. With Chrome, everything works fine. But I need to use Firefox, and there something breaks.

I am automating the testing of a Dojo UI, and need to wait while the Dojo UI does a lot of rendering. So here is what I do, and it works just fine in Chrome. Note that an implicit wait of 20 seconds is normally set in my code.

driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(By.id("contentframe"))); // relying on implicit wait 
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
(new WebDriverWait(driver, 120)).
     until(ExpectedConditions.elementToBeClickable(By.id("some_id")));

I have simplified the code so you don't see how the implicit wait is set back to 20 seconds. When the problem happens, it does not get there, anyway. The WebDriverWait causes an exception. The exception says TypeError: can't access dead object

There is a corresponding message from inside the wait:

May 16, 2017 3:36:11 PM org.openqa.selenium.support.ui.ExpectedConditions findElement
WARNING: WebDriverException thrown by findElement(By.id: 
some_id)
org.openqa.selenium.WebDriverException: TypeError: can't access dead object

There is also some JavaScript error output, apparently, by geckodriver:

JavaScript error: chrome://marionette/content/listener.js, line 1555: TypeError: can't access dead object
*************************
A coding exception was thrown and uncaught in a Task.

Full message: TypeError: can't access dead object
Full stack: find_@chrome://marionette/content/element.js:284:7
element.find/</findElements<@chrome://marionette/content/element.js:255:15
implicitlyWaitFor/</elementSearch@chrome://marionette/content/element.js:600:15
implicitlyWaitFor/<@chrome://marionette/content/element.js:627:5
implicitlyWaitFor@chrome://marionette/content/element.js:593:10
element.find/<@chrome://marionette/content/element.js:254:24
element.find@chrome://marionette/content/element.js:253:10
findElementsContent@chrome://marionette/content/listener.js:1314:19
TaskImpl_run@resource://gre/modules/Task.jsm:319:42
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
TaskImpl_handleResultValue@resource://gre/modules/Task.jsm:389:16
TaskImpl_run@resource://gre/modules/Task.jsm:327:15
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
dispatch/<@chrome://marionette/content/listener.js:186:15

*************************
*************************
A coding exception was thrown and uncaught in a Task.

Full message: TypeError: can't access dead object
Full stack: find_@chrome://marionette/content/element.js:284:7
element.find/</findElements<@chrome://marionette/content/element.js:255:15
implicitlyWaitFor/</elementSearch@chrome://marionette/content/element.js:600:15
implicitlyWaitFor/<@chrome://marionette/content/element.js:627:5
implicitlyWaitFor@chrome://marionette/content/element.js:593:10
element.find/<@chrome://marionette/content/element.js:254:24
element.find@chrome://marionette/content/element.js:253:10
findElementsContent@chrome://marionette/content/listener.js:1314:19
TaskImpl_run@resource://gre/modules/Task.jsm:319:42
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
TaskImpl_handleResultValue@resource://gre/modules/Task.jsm:389:16
TaskImpl_run@resource://gre/modules/Task.jsm:327:15
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
dispatch/<@chrome://marionette/content/listener.js:186:15

Moreover, my automatic exception processing tries to take a screenshot but that fails with the very same error. The code line is:

File snapshotTempFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE); And this time the output from geckodriver is:

A coding exception was thrown and uncaught in a Task.

Full message: TypeError: can't access dead object
Full stack: capture.viewport@chrome://marionette/content/capture.js:65:7
takeScreenshot@chrome://marionette/content/listener.js:1782:14
dispatch/</req<@chrome://marionette/content/listener.js:188:22
TaskImpl_run@resource://gre/modules/Task.jsm:319:42
TaskImpl@resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction@resource://gre/modules/Task.jsm:252:14
Task_spawn@resource://gre/modules/Task.jsm:166:12
dispatch/<@chrome://marionette/content/listener.js:186:15

So, can I do anything to make this work properly? And is this something I need to raise as a geckodriver bug?

The only thing I could google out is this: https://github.com/mozilla/geckodriver/issues/614 and the only proposed solution there is driver.switchTo().defaultContent() . This might fix my screenshot routine, but the element I am waiting for is inside the content frame, so I can't use this fix for the wait.

Mikhail Ramendik
  • 1,063
  • 2
  • 12
  • 26

3 Answers3

4

Not sure if this will help you but when I ran into this error message, I was able to get past it by having:

driver.switchTo().defaultContent();

driver.switchTo().frame(0);

between each interaction with an element in the iframe.

Example:

driver.switchTo().frame(0);
    myPage.selectElement(getCycleSummary());
    driver.switchTo().defaultContent();
    driver.switchTo().frame(0);
    myPage.selectDisplayedElement(this.getCycleBtn());

Without the driver switches I would receive the dead object error.

jwest
  • 41
  • 3
3

It looks like the frame is reloaded with a new reference while you are waiting for the element some_id. I would classify this issue as a bug since the error returned by the driver is not defined by the WebDriver protocol.

Your best chance to make it work is probably to implement a custom waiter to locate the frame/element and skip unhandled exceptions:

WebElement elem = waiter.Until(elementToBeClickableInFrame(By.id("contentframe"),
                                                           By.id("some_id")));
public static ExpectedCondition<WebElement> elementToBeClickableInFrame(final By locatorFrame, final By locator) {
  return new ExpectedCondition<WebElement>() {

    @Override
    public WebElement apply(WebDriver driver) {
      try {

        driver.switchTo().defaultContent();
        driver.switchTo().frame(driver.findElement(locatorFrame));

        WebElement elem = driver.findElement(locator);
        return elem.isDisplayed() && elem.isEnabled() ? elem : null;

      } catch (Exception e) {
        return null;
      }
    }

    @Override
    public String toString() {
      return "element located by: " + locator + " in " + locatorFrame;
    }
  };
}
Florent B.
  • 41,537
  • 7
  • 86
  • 101
  • Thanks! This has worked. (I have modified it to use a separate class definition instead of a braces initialization). I have eventually found the issue on the geckodriver tracker, and with this answer I knew how to put a comment in. I have done do. Issue is at https://github.com/mozilla/geckodriver/issues/614 – Mikhail Ramendik May 17 '17 at 12:45
0

See,

There Should be a format which i am giving below:

  1. First switch to frame. (Switch to default first in case already you are in another frame).

  2. Perform your action (click on any element)

  3. Switch to default content again. (if you do not switch it back, it creates problem).

         driver.switchTo().defaultContent();
    
         driver.switchTo().frame(locator or name of the frame);
    
    
         driver.click(your element locator);
    
    
         driver.switchTo().defaultContent();